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,25 @@
1
+ require 'thor'
2
+ require 'generamba/version.rb'
3
+
4
+ module Generamba::CLI
5
+ class Application < Thor
6
+ include Generamba
7
+
8
+ desc 'version', 'Prints out Generamba current version'
9
+ def version
10
+ options = {}
11
+ options['Version'] = Generamba::VERSION.green
12
+ options['Release date'] = Generamba::RELEASE_DATE.green
13
+ options['Change notes'] = Generamba::RELEASE_LINK.green
14
+
15
+ values = []
16
+
17
+ options.each do |title, value|
18
+ values.push("#{title}: #{value}")
19
+ end
20
+
21
+ output = values.join("\n")
22
+ puts(output)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,41 @@
1
+ ### Headers settings
2
+ company: {{ company }}
3
+
4
+ ### Xcode project settings
5
+ project_name: {{ project_name }}
6
+ xcodeproj_path: {{ xcodeproj_path }}
7
+ {% if prefix != "" %}prefix: {{ prefix }}{% endif %}
8
+
9
+ {% if (project_target != nil and project_target != "") or (project_file_path != nil and project_file_path != "") or (project_group_path != nil and project_group_path != "") %}### Code generation settings section
10
+ {% if project_target != nil and project_target != "" %}# The main project target name
11
+ project_target: {{ project_target }}{% endif %}
12
+
13
+ {% if project_file_path != nil and project_file_path != "" %}# The file path for new modules
14
+ project_file_path: {{ project_file_path }}{% endif %}
15
+
16
+ {% if project_group_path != nil and project_group_path != "" %}# The Xcode group path to new modules
17
+ project_group_path: {{ project_group_path }}{% endif %}
18
+ {% endif %}
19
+
20
+ {% if (test_target != nil and test_target != "") or (test_file_path != nil and test_file_path != "") or (test_group_path != nil and test_group_path != "") %}### Tests generation settings section
21
+ {% if test_target != nil and test_target != "" %}# The tests target name
22
+ test_target: {{ test_target }}{% endif %}
23
+
24
+ {% if test_file_path != nil and test_file_path != "" %}# The file path for new tests
25
+ test_file_path: {{ test_file_path }}{% endif %}
26
+
27
+ {% if test_group_path != nil and test_group_path != "" %}# The Xcode group path to new tests
28
+ test_group_path: {{ test_group_path }}{% endif %}
29
+ {% endif %}
30
+
31
+ {% if podfile_path != nil or cartfile_path != nil %}### Dependencies settings section{% endif %}
32
+ {% if podfile_path != nil %}podfile_path: {{ podfile_path }}{% endif %}
33
+ {% if cartfile_path != nil %}cartfile_path: {{ cartfile_path }}{% endif %}
34
+
35
+ ### Templates
36
+ templates:
37
+ {% if templates.size > 0 %}{% for item in templates %}- {{ item }}
38
+ {% endfor %}{% else %}#- {name: local_template_name, local: 'absolute/file/path'}
39
+ #- {name: remote_template_name, git: 'https://github.com/igrekde/remote_template'}
40
+ #- {name: catalog_template_name}
41
+ {% endif %}
@@ -0,0 +1,100 @@
1
+ module Generamba
2
+
3
+ SLASH_REGEX = /^\/|\/$/
4
+ C99IDENTIFIER = /[^\w]/
5
+
6
+ PATH_TYPE_PROJECT = 'project'
7
+ PATH_TYPE_TEST = 'test'
8
+
9
+ # Represents currently generating code module
10
+ class CodeModule
11
+ attr_reader :name,
12
+ :description,
13
+ :author,
14
+ :company,
15
+ :year,
16
+ :prefix,
17
+ :project_name,
18
+ :product_module_name,
19
+ :xcodeproj_path,
20
+ :project_file_path,
21
+ :project_group_path,
22
+ :test_file_path,
23
+ :test_group_path,
24
+ :project_targets,
25
+ :test_targets,
26
+ :podfile_path,
27
+ :cartfile_path,
28
+ :custom_parameters
29
+
30
+ def initialize(name, rambafile, options)
31
+ # Base initialization
32
+ @name = name
33
+ @description = options[:description] ? options[:description] : "#{name} module"
34
+ @author = rambafile[AUTHOR_NAME_KEY] ? rambafile[AUTHOR_NAME_KEY] : UserPreferences.obtain_username
35
+ @company = rambafile[COMPANY_KEY]
36
+ @year = Time.now.year.to_s
37
+
38
+ @prefix = rambafile[PROJECT_PREFIX_KEY]
39
+ @project_name = rambafile[PROJECT_NAME_KEY]
40
+
41
+ @product_module_name = rambafile[PRODUCT_MODULE_NAME_KEY]
42
+ @product_module_name = @project_name.gsub(C99IDENTIFIER, '_') if !@product_module_name && @project_name
43
+
44
+ @xcodeproj_path = rambafile[XCODEPROJ_PATH_KEY]
45
+
46
+ setup_file_and_group_paths(rambafile[PROJECT_FILE_PATH_KEY], rambafile[PROJECT_GROUP_PATH_KEY], PATH_TYPE_PROJECT)
47
+ setup_file_and_group_paths(rambafile[TEST_FILE_PATH_KEY], rambafile[TEST_GROUP_PATH_KEY], PATH_TYPE_TEST)
48
+
49
+ @project_targets = [rambafile[PROJECT_TARGET_KEY]] if rambafile[PROJECT_TARGET_KEY]
50
+ @project_targets = rambafile[PROJECT_TARGETS_KEY] if rambafile[PROJECT_TARGETS_KEY]
51
+
52
+ @test_targets = [rambafile[TEST_TARGET_KEY]] if rambafile[TEST_TARGET_KEY]
53
+ @test_targets = rambafile[TEST_TARGETS_KEY] if rambafile[TEST_TARGETS_KEY]
54
+
55
+ # Custom parameters
56
+ @custom_parameters = options[:custom_parameters]
57
+
58
+ # Options adaptation
59
+ @author = options[:author] if options[:author]
60
+ @project_targets = options[:project_targets].split(',') if options[:project_targets]
61
+ @test_targets = options[:test_targets].split(',') if options[:test_targets]
62
+
63
+ setup_file_and_group_paths(options[:project_file_path], options[:project_group_path], PATH_TYPE_PROJECT)
64
+ setup_file_and_group_paths(options[:test_file_path], options[:test_group_path], PATH_TYPE_TEST)
65
+
66
+ # The priority is given to `module_path` and 'test_path' options
67
+ setup_file_and_group_paths(options[:module_path], options[:module_path], PATH_TYPE_PROJECT)
68
+ setup_file_and_group_paths(options[:test_path], options[:test_path], PATH_TYPE_TEST)
69
+
70
+ @podfile_path = rambafile[PODFILE_PATH_KEY] if rambafile[PODFILE_PATH_KEY]
71
+ @cartfile_path = rambafile[CARTFILE_PATH_KEY] if rambafile[CARTFILE_PATH_KEY]
72
+ end
73
+
74
+ private
75
+
76
+ def setup_file_and_group_paths(file_path, group_path, path_type)
77
+ if file_path || group_path
78
+ variable_name = "#{path_type}_file_path"
79
+
80
+ if file_path || !instance_variable_get("@#{variable_name}")
81
+ file_path = group_path unless file_path
82
+
83
+ variable_value = file_path.gsub(SLASH_REGEX, '')
84
+ variable_value = Pathname.new(variable_value).join(@name)
85
+ instance_variable_set("@#{variable_name}", variable_value)
86
+ end
87
+
88
+ variable_name = "#{path_type}_group_path"
89
+
90
+ if group_path || !instance_variable_get("@#{variable_name}")
91
+ group_path = file_path unless group_path
92
+
93
+ variable_value = group_path.gsub(SLASH_REGEX, '')
94
+ variable_value = Pathname.new(variable_value).join(@name)
95
+ instance_variable_set("@#{variable_name}", variable_value)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,43 @@
1
+ require 'liquid'
2
+
3
+ module Generamba
4
+
5
+ # Responsible for generating code using provided liquid templates
6
+ class ContentGenerator
7
+
8
+ # Generates and returns a filename and a body of a specific code file.
9
+ # @param file [Hash<String,String>] A hashmap with template's filename and filepath
10
+ # @param scope [Hash<String,String>] A hashmap with module info
11
+ # @param template [ModuleTemplate] The model describing a Generamba template used for code generation
12
+ #
13
+ # @return [String], [String] The generated file_name and body
14
+ def self.create_file(file, scope, template)
15
+ file_source = IO.read(template.template_path.join(file[TEMPLATE_FILE_PATH_KEY]))
16
+ Liquid::Template.file_system = Liquid::LocalFileSystem.new(template.template_path.join('snippets'), '%s.liquid')
17
+
18
+ template = Liquid::Template.parse(file_source)
19
+ filename_template = self.file_name_template(file)
20
+
21
+ file_basename = File.basename(file[TEMPLATE_FILE_NAME_KEY])
22
+
23
+ module_info = scope['module_info']
24
+
25
+ module_info['file_basename'] = file_basename
26
+
27
+ file_name = filename_template.render(scope)
28
+
29
+ module_info['file_name'] = file_name
30
+ module_info.delete('file_basename')
31
+
32
+ content = template.render(scope)
33
+
34
+ return file_name, content
35
+ end
36
+
37
+ def self.file_name_template(file)
38
+ template_default_text = '{{ prefix }}{{ module_info.name }}{{ module_info.file_basename }}'
39
+ template_text = file[TEMPLATE_FILE_CUSTOM_NAME_KEY] || template_default_text
40
+ return Liquid::Template.parse(template_text)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ require 'generamba/helpers/template_helper.rb'
2
+
3
+ module Generamba
4
+
5
+ # Represents a single Generamba module template
6
+ class ModuleTemplate
7
+ attr_reader :template_name, :template_path, :code_files, :test_files, :dependencies
8
+
9
+ def initialize(name, options = nil)
10
+ spec_path = TemplateHelper.obtain_spec(name)
11
+
12
+ unless options
13
+ spec = YAML.load_file(spec_path)
14
+ else
15
+ spec_source = IO.read(spec_path)
16
+ spec_template = Liquid::Template.parse(spec_source)
17
+ spec_content = spec_template.render(options)
18
+ spec = YAML.load(spec_content)
19
+ end
20
+
21
+ @code_files = spec[TEMPLATE_CODE_FILES_KEY]
22
+ @test_files = spec[TEMPLATE_TEST_FILES_KEY]
23
+ @template_name = spec[TEMPLATE_NAME_KEY]
24
+ @template_path = TemplateHelper.obtain_path(name)
25
+ @dependencies = spec[TEMPLATE_DEPENDENCIES_KEY]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ require 'liquid'
2
+
3
+ module Generamba
4
+
5
+ # Responsible for creating Generamba configs
6
+ class RambafileGenerator
7
+
8
+ # Creates a Rambafile using the provided properties hashmap
9
+ # @param properties Rambafile properties
10
+ #
11
+ # @return void
12
+ def self.create_rambafile(properties)
13
+ file_source = IO.read(File.dirname(__FILE__) + '/Rambafile.liquid')
14
+
15
+ template = Liquid::Template.parse(file_source)
16
+ output = template.render(properties).gsub!(/[\n]{3,}/, "\n\n");
17
+
18
+ File.open(RAMBAFILE_NAME, 'w+') {|f|
19
+ f.write(output)
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,50 @@
1
+ require 'generamba/constants/user_preferences_constants.rb'
2
+
3
+ module Generamba
4
+
5
+ # A class that provides methods for working with user-specific information.
6
+ # Currently it has methods for obtaining and saving username, later it may be improved to something more general.
7
+ class UserPreferences
8
+
9
+ def self.obtain_username
10
+ path = obtain_user_preferences_path
11
+
12
+ file_contents = open(path).read
13
+ preferences = file_contents.empty? ? {} : YAML.load(file_contents).to_hash
14
+
15
+ return preferences[USERNAME_KEY]
16
+ end
17
+
18
+ def self.save_username(username)
19
+ path = obtain_user_preferences_path
20
+
21
+ file_contents = open(path).read
22
+ preferences = file_contents.empty? ? {} : YAML.load(file_contents).to_hash
23
+
24
+ preferences[USERNAME_KEY] = username
25
+ File.open(path, 'w+') { |f| f.write(preferences.to_yaml) }
26
+ end
27
+
28
+ private
29
+
30
+ def self.obtain_user_preferences_path
31
+ home_path = Pathname.new(ENV['HOME'])
32
+ .join(GENERAMBA_HOME_DIR)
33
+
34
+ path_exists = Dir.exist?(home_path)
35
+
36
+ unless path_exists
37
+ FileUtils.mkdir_p home_path
38
+ end
39
+
40
+ preferences_path = home_path.join(USER_PREFERENCES_FILE)
41
+ preferences_exist = File.file?(preferences_path)
42
+
43
+ unless preferences_exist
44
+ File.open(preferences_path, 'w+') { |f| f.write('') }
45
+ end
46
+
47
+ return preferences_path
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module Generamba
2
+
3
+ # General constants
4
+ RAMBAFILE_NAME = 'Rambafile'
5
+ RAMBASPEC_EXTENSION = '.rambaspec'
6
+ TEMPLATES_FOLDER = 'Templates'
7
+ RAMBLER_CATALOG_REPO = 'https://github.com/rambler-digital-solutions/generamba-catalog'
8
+ GENERAMBA_CATALOG_NAME = 'generamba-catalog'
9
+ GENERAMBA_HOME_DIR = '.generamba'
10
+ CATALOGS_DIR = 'catalogs'
11
+ USER_PREFERENCES_FILE = 'user_preferences.yml'
12
+ end
@@ -0,0 +1,31 @@
1
+ module Generamba
2
+
3
+ # Keys of Rambafile files
4
+ COMPANY_KEY = 'company'
5
+ AUTHOR_NAME_KEY = 'author'
6
+ PROJECT_NAME_KEY = 'project_name'
7
+ PROJECT_PREFIX_KEY = 'prefix'
8
+ XCODEPROJ_PATH_KEY = 'xcodeproj_path'
9
+
10
+ PROJECT_TARGET_KEY = 'project_target'
11
+ PROJECT_TARGETS_KEY = 'project_targets'
12
+ PROJECT_FILE_PATH_KEY = 'project_file_path'
13
+ PROJECT_GROUP_PATH_KEY = 'project_group_path'
14
+
15
+ PRODUCT_MODULE_NAME_KEY = 'product_module_name'
16
+
17
+ TEST_TARGET_KEY = 'test_target'
18
+ TEST_TARGETS_KEY = 'test_targets'
19
+ TEST_FILE_PATH_KEY = 'test_file_path'
20
+ TEST_GROUP_PATH_KEY = 'test_group_path'
21
+
22
+ PODFILE_PATH_KEY = 'podfile_path'
23
+ CARTFILE_PATH_KEY = 'cartfile_path'
24
+
25
+ CATALOGS_KEY = 'catalogs'
26
+ TEMPLATES_KEY = 'templates'
27
+ TEMPLATE_DECLARATION_NAME_KEY = 'name'
28
+ TEMPLATE_DECLARATION_LOCAL_KEY = 'local'
29
+ TEMPLATE_DECLARATION_GIT_KEY = 'git'
30
+ TEMPLATE_DECLARATION_BRANCH_KEY = 'branch'
31
+ end
@@ -0,0 +1,18 @@
1
+ module Generamba
2
+
3
+ # Keys of .rambaspec files
4
+ TEMPLATE_NAME_KEY = 'name'
5
+ TEMPLATE_SUMMARY_KEY = 'summary'
6
+ TEMPLATE_AUTHOR_KEY = 'author'
7
+ TEMPLATE_VERSION_KEY = 'version'
8
+ TEMPLATE_LICENSE_KEY = 'license'
9
+
10
+ TEMPLATE_CODE_FILES_KEY = 'code_files'
11
+ TEMPLATE_TEST_FILES_KEY = 'test_files'
12
+ TEMPLATE_FILE_NAME_KEY = 'name'
13
+ TEMPLATE_FILE_CUSTOM_NAME_KEY = 'custom_name'
14
+ TEMPLATE_FILE_PATH_KEY = 'path'
15
+ TEMPLATE_FILE_IS_RESOURCE_KEY = 'is_resource'
16
+
17
+ TEMPLATE_DEPENDENCIES_KEY = 'dependencies'
18
+ end
@@ -0,0 +1,5 @@
1
+ module Generamba
2
+
3
+ # Keys of file user_preferences.yml
4
+ USERNAME_KEY = 'username'
5
+ end
@@ -0,0 +1,54 @@
1
+ require 'cocoapods-core'
2
+
3
+ module Generamba
4
+ # Provides methods for check dependencies from rambaspec in podfile
5
+ class DependencyChecker
6
+ # Check Podfile for dependencies
7
+ # @param dependencies [Array] Array of dependencies name
8
+ # @param podfile_path [String] String of Podfile path
9
+ #
10
+ # @return [void]
11
+ def self.check_all_required_dependencies_has_in_podfile(dependencies, podfile_path)
12
+ return if !dependencies || dependencies.count == 0 || !podfile_path
13
+
14
+ dependencies_names = []
15
+ Pod::Podfile.from_file(Pathname.new(podfile_path)).dependencies.each do |dependency|
16
+ dependencies_names.push(dependency.name.gsub(/ .*/, ''))
17
+ end
18
+
19
+ not_existing_dependency = []
20
+
21
+ dependencies.each do |dependency_name|
22
+ unless dependencies_names.include?(dependency_name)
23
+ not_existing_dependency.push(dependency_name)
24
+ end
25
+ end
26
+
27
+ if not_existing_dependency.count > 0
28
+ puts "[Warning] Dependencies #{not_existing_dependency} missed in Podfile".yellow
29
+ end
30
+ end
31
+
32
+ # Check Cartfile for dependencies
33
+ # @param dependencies [Array] Array of dependencies name
34
+ # @param cartfile_path [String] String of Podfile path
35
+ #
36
+ # @return [void]
37
+ def self.check_all_required_dependencies_has_in_cartfile(dependencies, cartfile_path)
38
+ return if !dependencies || dependencies.count == 0 || !cartfile_path
39
+
40
+ cartfile_string = File.read(cartfile_path)
41
+
42
+ not_existing_dependency = []
43
+ dependencies.each do |dependency_name|
44
+ unless cartfile_string.include?(dependency_name)
45
+ not_existing_dependency.push(dependency_name)
46
+ end
47
+ end
48
+
49
+ if not_existing_dependency.count > 0
50
+ puts "[Warning] Dependencies #{not_existing_dependency} missed in Cartfile".yellow
51
+ end
52
+ end
53
+ end
54
+ end