generamba 0.6.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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +64 -0
  6. data/LICENSE.txt +21 -0
  7. data/Rakefile +6 -0
  8. data/Readme.md +51 -0
  9. data/bin/GenerambaSandbox/Rambafile +17 -0
  10. data/bin/console +14 -0
  11. data/bin/generamba +5 -0
  12. data/bin/setup +7 -0
  13. data/generamba.gemspec +31 -0
  14. data/lib/generamba.rb +17 -0
  15. data/lib/generamba/cli/cli.rb +15 -0
  16. data/lib/generamba/cli/gen_command.rb +26 -0
  17. data/lib/generamba/cli/setup_command.rb +80 -0
  18. data/lib/generamba/cli/template/template_create_command.rb +29 -0
  19. data/lib/generamba/cli/template/template_group.rb +12 -0
  20. data/lib/generamba/cli/template/template_install_command.rb +10 -0
  21. data/lib/generamba/cli/thor_extension.rb +34 -0
  22. data/lib/generamba/code_generation/Rambafile.liquid +37 -0
  23. data/lib/generamba/code_generation/code_module.rb +32 -0
  24. data/lib/generamba/code_generation/content_generator.rb +42 -0
  25. data/lib/generamba/code_generation/module_template.rb +20 -0
  26. data/lib/generamba/code_generation/rambafile_generator.rb +22 -0
  27. data/lib/generamba/configuration/project_configuration.rb +9 -0
  28. data/lib/generamba/configuration/user_preferences.rb +50 -0
  29. data/lib/generamba/constants/constants.rb +12 -0
  30. data/lib/generamba/constants/rambafile_constants.rb +24 -0
  31. data/lib/generamba/constants/rambaspec_constants.rb +16 -0
  32. data/lib/generamba/constants/user_preferences_constants.rb +5 -0
  33. data/lib/generamba/helpers/template_helper.rb +32 -0
  34. data/lib/generamba/helpers/xcodeproj_helper.rb +87 -0
  35. data/lib/generamba/module_generator.rb +97 -0
  36. data/lib/generamba/template/creator/new_template/Code/Service/service.h.liquid +11 -0
  37. data/lib/generamba/template/creator/new_template/Code/Service/service.m.liquid +13 -0
  38. data/lib/generamba/template/creator/new_template/Tests/Service/service_tests.m.liquid +35 -0
  39. data/lib/generamba/template/creator/new_template/template.rambaspec.liquid +20 -0
  40. data/lib/generamba/template/creator/template_creator.rb +38 -0
  41. data/lib/generamba/template/helpers/rambaspec_validator.rb +47 -0
  42. data/lib/generamba/template/installer/abstract_installer.rb +9 -0
  43. data/lib/generamba/template/installer/catalog_installer.rb +40 -0
  44. data/lib/generamba/template/installer/local_installer.rb +32 -0
  45. data/lib/generamba/template/installer/remote_installer.rb +43 -0
  46. data/lib/generamba/template/processor/template_declaration.rb +34 -0
  47. data/lib/generamba/template/processor/template_processor.rb +77 -0
  48. data/lib/generamba/version.rb +3 -0
  49. metadata +221 -0
@@ -0,0 +1,97 @@
1
+ require 'fileutils'
2
+
3
+ require 'generamba/helpers/xcodeproj_helper.rb'
4
+
5
+ module Generamba
6
+
7
+ # Responsible for creating the whole code module using information from the CLI
8
+ class ModuleGenerator
9
+
10
+ def generate_module(template_name, name, description)
11
+ # Setting up CodeModule and ModuleTemplate objects.
12
+ # TODO: Move it to the CLI infrastructure
13
+ code_module = CodeModule.new(name, description)
14
+ template = ModuleTemplate.new(template_name)
15
+
16
+ # Setting up Xcode objects
17
+ project = XcodeprojHelper.obtain_project(ProjectConfiguration.xcodeproj_path)
18
+ project_target = XcodeprojHelper.obtain_target(ProjectConfiguration.project_target,
19
+ project)
20
+ test_target = XcodeprojHelper.obtain_target(ProjectConfiguration.test_target,
21
+ project)
22
+
23
+ # Configuring file paths
24
+ module_dir_path = Pathname.new(ProjectConfiguration.project_file_path)
25
+ .join(name)
26
+ test_dir_path = Pathname.new(ProjectConfiguration.test_file_path)
27
+ .join(name)
28
+ FileUtils.mkdir_p module_dir_path
29
+ FileUtils.mkdir_p test_dir_path
30
+
31
+ # Configuring group paths
32
+ module_group_path = Pathname.new(ProjectConfiguration.project_group_path)
33
+ .join(name)
34
+ test_group_path = Pathname.new(ProjectConfiguration.test_group_path)
35
+ .join(name)
36
+
37
+ # Creating code files
38
+ puts('Creating code files...')
39
+ process_files(template.code_files,
40
+ name,
41
+ code_module,
42
+ template,
43
+ project,
44
+ project_target,
45
+ module_group_path,
46
+ module_dir_path)
47
+
48
+ # Creating test files
49
+ puts('Creating test files...')
50
+ process_files(template.test_files,
51
+ name,
52
+ code_module,
53
+ template,
54
+ project,
55
+ test_target,
56
+ test_group_path,
57
+ test_dir_path)
58
+
59
+ # Saving the current changes in the Xcode project
60
+ project.save
61
+ puts("Module #{name} successfully created!")
62
+ end
63
+
64
+ def process_files(files, name, code_module, template, project, target, group_path, dir_path)
65
+ XcodeprojHelper.clear_group(project, group_path)
66
+ files.each do |file|
67
+ # The target file's name consists of three parameters: project prefix, module name and template file name.
68
+ # E.g. RDS + Authorization + Presenter.h = RDSAuthorizationPresenter.h
69
+ file_basename = name + File.basename(file[TEMPLATE_NAME_KEY])
70
+ prefix = ProjectConfiguration.prefix
71
+ file_name = prefix ? prefix + file_basename : file_basename
72
+
73
+ file_group = File.dirname(file[TEMPLATE_NAME_KEY])
74
+
75
+ # Generating the content of the code file
76
+ file_content = ContentGenerator.create_file_content(file,
77
+ code_module,
78
+ template)
79
+ file_path = dir_path
80
+ .join(file_group)
81
+ .join(file_name)
82
+
83
+ # Creating the file in the filesystem
84
+ FileUtils.mkdir_p File.dirname(file_path)
85
+ File.open(file_path, 'w+') do |f|
86
+ f.write(file_content)
87
+ end
88
+
89
+ # Creating the file in the Xcode project
90
+ XcodeprojHelper.add_file_to_project_and_target(project,
91
+ target,
92
+ group_path.join(file_group),
93
+ file_path)
94
+ end
95
+ end
96
+ end
97
+ 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,38 @@
1
+ module Generamba
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__))
17
+ .join(NEW_TEMPLATE_FOLDER)
18
+ rambaspec_template_file_path = template_dir_path.join(RAMBASPEC_TEMPLATE_NAME)
19
+ code_file_path = template_dir_path.join(CODE_FOLDER)
20
+ tests_file_path = template_dir_path.join(TESTS_FOLDER)
21
+
22
+ template = Tilt.new(rambaspec_template_file_path)
23
+ output = template.render(properties)
24
+
25
+ result_name = properties[TEMPLATE_NAME_KEY] + RAMBASPEC_EXTENSION
26
+ result_dir_path = Pathname.new(properties[TEMPLATE_NAME_KEY])
27
+
28
+ FileUtils.mkdir_p result_dir_path
29
+ FileUtils.cp_r(code_file_path, result_dir_path)
30
+ FileUtils.cp_r(tests_file_path, result_dir_path)
31
+
32
+ File.open(result_dir_path.join(result_name), 'w+') {|f|
33
+ f.write(output)
34
+ }
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,47 @@
1
+ require 'settingslogic'
2
+
3
+ module Generamba
4
+
5
+ # Provides methods that validate .rambaspec file existance and structure
6
+ class RambaspecValidator
7
+
8
+ # Validates the existance of a .rambaspec file for a given template
9
+ #
10
+ # @param template_name [String] The name of the template
11
+ # @param template_path [String] The local filepath to the template
12
+ #
13
+ # @return [Bool]
14
+ def self.validate_spec_existance(template_name, template_path)
15
+ local_spec_path = self.obtain_spec_path(template_name, template_path)
16
+ rambaspec_exist = File.file?(local_spec_path)
17
+ end
18
+
19
+ # Validates the structure of a .rambaspec file for a given template
20
+ #
21
+ # @param template_name [String] The name of the template
22
+ # @param template_path [String] The local filepath to the template
23
+ #
24
+ # @return [Bool]
25
+ def self.validate_spec(template_name, template_path)
26
+ spec_path = self.obtain_spec_path(template_name, template_path)
27
+ spec = Settingslogic.new(spec_path)
28
+
29
+ is_spec_valid = spec.name != nil && spec.author != nil && spec.version != nil && spec.code_files != nil
30
+ return is_spec_valid
31
+ end
32
+
33
+ private
34
+
35
+ # Returns a filepath for a given .rambaspec filename
36
+ #
37
+ # @param template_name [String] The name of the template
38
+ # @param template_path [String] The local filepath to the template
39
+ #
40
+ # @return [Bool]
41
+ def self.obtain_spec_path(template_name, template_path)
42
+ spec_filename = template_name + RAMBASPEC_EXTENSION
43
+ full_path = Pathname.new(template_path)
44
+ .join(spec_filename)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,9 @@
1
+ module Generamba
2
+
3
+ # Abstract template installer class
4
+ class AbstractInstaller
5
+ def install_template(template_declaration)
6
+ raise 'Abstract Method - you should implement it in the concrete subclass'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ require 'generamba/template/installer/abstract_installer.rb'
2
+ require 'generamba/template/helpers/rambaspec_validator.rb'
3
+ require 'fileutils'
4
+ require 'tmpdir'
5
+
6
+ module Generamba
7
+
8
+ # Incapsulates the logic of installing Generamba templates from the template catalog
9
+ class CatalogInstaller < AbstractInstaller
10
+ def install_template(template_declaration)
11
+ template_name = template_declaration.name
12
+ puts("Installing #{template_name}...")
13
+
14
+ template_name = template_declaration.name
15
+ catalog_path = Pathname.new(ENV['HOME'])
16
+ .join(GENERAMBA_HOME_DIR)
17
+ .join(CATALOGS_DIR)
18
+ .join(GENERAMBA_CATALOG_NAME)
19
+ template_path = catalog_path.join(template_name)
20
+
21
+ rambaspec_exist = Generamba::RambaspecValidator.validate_spec_existance(template_name, template_path)
22
+
23
+ if rambaspec_exist == false
24
+ error_description = "Cannot find #{template_name + RAMBASPEC_EXTENSION} in the template catalog. Try another name."
25
+ raise StandardError.new(error_description)
26
+ end
27
+
28
+ rambaspec_valid = Generamba::RambaspecValidator.validate_spec(template_name, template_path)
29
+ if rambaspec_valid == false
30
+ error_description = "#{template_name + RAMBASPEC_EXTENSION} is not valid."
31
+ raise StandardError.new(error_description)
32
+ end
33
+
34
+ install_path = Pathname.new(TEMPLATES_FOLDER)
35
+ .join(template_name)
36
+ FileUtils.mkdir_p install_path
37
+ FileUtils.copy_entry(template_path, install_path)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ require 'generamba/template/installer/abstract_installer.rb'
2
+ require 'generamba/template/helpers/rambaspec_validator.rb'
3
+
4
+ module Generamba
5
+
6
+ # Incapsulates the logic of verifying and installing local templates
7
+ class LocalInstaller < AbstractInstaller
8
+ def install_template(template_declaration)
9
+ template_name = template_declaration.name
10
+ puts("Installing #{template_name}...")
11
+
12
+ local_path = template_declaration.local
13
+ rambaspec_exist = Generamba::RambaspecValidator.validate_spec_existance(template_name, local_path)
14
+
15
+ if rambaspec_exist == false
16
+ error_description = "Cannot find #{template_name + RAMBASPEC_EXTENSION} in the specified directory. Try another path or name."
17
+ raise StandardError.new(error_description)
18
+ end
19
+
20
+ rambaspec_valid = Generamba::RambaspecValidator.validate_spec(template_name, local_path)
21
+ if rambaspec_valid == false
22
+ error_description = "#{template_name + RAMBASPEC_EXTENSION} is not valid."
23
+ raise StandardError.new(error_description)
24
+ end
25
+
26
+ install_path = Pathname.new(TEMPLATES_FOLDER)
27
+ .join(template_name)
28
+ FileUtils.mkdir_p install_path
29
+ FileUtils.copy_entry(local_path, install_path)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,43 @@
1
+ require 'generamba/template/installer/abstract_installer.rb'
2
+ require 'generamba/template/helpers/rambaspec_validator.rb'
3
+ require 'git'
4
+ require 'fileutils'
5
+ require 'tmpdir'
6
+
7
+ module Generamba
8
+
9
+ # Incapsulates the logic of fetching remote templates, verifying and installing them
10
+ class RemoteInstaller < AbstractInstaller
11
+ def install_template(template_declaration)
12
+ template_name = template_declaration.name
13
+ puts("Installing #{template_name}...")
14
+
15
+ repo_url = template_declaration.git
16
+
17
+ temp_path = Dir.tmpdir()
18
+ template_dir = Pathname.new(temp_path)
19
+ .join(template_name)
20
+ Git.clone(repo_url, template_name, :path => temp_path)
21
+
22
+ rambaspec_exist = Generamba::RambaspecValidator.validate_spec_existance(template_name, template_dir)
23
+ if rambaspec_exist == false
24
+ FileUtils.rm_rf(temp_path)
25
+ error_description = "Cannot find #{template_name + RAMBASPEC_EXTENSION} in the root directory of specified repository."
26
+ raise StandardError.new(error_description)
27
+ end
28
+
29
+ rambaspec_valid = Generamba::RambaspecValidator.validate_spec(template_name, template_dir)
30
+ if rambaspec_valid == false
31
+ error_description = "#{template_name + RAMBASPEC_EXTENSION} is not valid."
32
+ raise StandardError.new(error_description)
33
+ end
34
+
35
+ install_path = Pathname.new(TEMPLATES_FOLDER)
36
+ .join(template_name)
37
+ FileUtils.mkdir_p install_path
38
+ FileUtils.copy_entry(template_dir, install_path)
39
+
40
+ FileUtils.rm_rf(temp_path)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,34 @@
1
+ module Generamba
2
+
3
+ # This class acts as an Enumeration for TemplateDeclaration types
4
+ class TemplateDeclarationType
5
+ # A local template - usually it's stored somewhere outside the current project directory
6
+ LOCAL_TEMPLATE = 0
7
+
8
+ # A remote template - it's stored in a remote Git repository
9
+ REMOTE_TEMPLATE = 1
10
+
11
+ # A template from our shared catalog
12
+ CATALOG_TEMPLATE = 2
13
+ end
14
+
15
+ # Describes a Generamba template declaration model
16
+ class TemplateDeclaration
17
+ attr_reader :name, :local, :git, :type
18
+
19
+ def initialize(template_hash)
20
+ @name = template_hash[TEMPLATE_DECLARATION_NAME_KEY]
21
+ @local = template_hash[TEMPLATE_DECLARATION_LOCAL_KEY]
22
+ @git = template_hash[TEMPLATE_DECLARATION_GIT_KEY]
23
+
24
+ @type = TemplateDeclarationType::LOCAL_TEMPLATE if @local
25
+ @type = TemplateDeclarationType::REMOTE_TEMPLATE if @git
26
+ @type = TemplateDeclarationType::CATALOG_TEMPLATE if @git == nil && @local == nil
27
+ end
28
+
29
+ def install(strategy)
30
+ strategy.install_template(self)
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,77 @@
1
+ require 'generamba/template/processor/template_declaration.rb'
2
+ require 'generamba/template/installer/local_installer.rb'
3
+ require 'generamba/template/installer/remote_installer.rb'
4
+ require 'generamba/template/installer/catalog_installer.rb'
5
+ require 'git'
6
+
7
+ module Generamba
8
+
9
+ # Incapsulates logic of processing templates declaration section from Rambafile
10
+ class TemplateProcessor
11
+
12
+ # This method parses Rambafile, serializes templates hashes into model objects and install them
13
+ def install_templates
14
+ # We always clear previously installed templates to avoid conflicts in different versions
15
+ clear_installed_templates
16
+
17
+ rambafile = YAML.load_file(RAMBAFILE_NAME)
18
+
19
+ # Mapping hashes to model objects
20
+ templates = rambafile[TEMPLATES_KEY].map { |template_hash|
21
+ template_declaration = Generamba::TemplateDeclaration.new(template_hash)
22
+ }
23
+
24
+ if !templates || templates.count == 0
25
+ error_description = 'You must specify at least one template in Rambafile under the key *project_templates*'
26
+ raise StandardError.new(error_description)
27
+ end
28
+
29
+ # If there is at least one template from the shared catalog, we should update our local copy of the catalog
30
+ update_shared_catalog_if_needed(templates)
31
+
32
+ templates.each do |template_declaration|
33
+ strategy = strategy_for_type(template_declaration.type)
34
+ template_declaration.install(strategy)
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ # Clears all of the currently installed templates
41
+ def clear_installed_templates
42
+ install_path = Pathname.new(TEMPLATES_FOLDER)
43
+ FileUtils.rm_rf(Dir.glob(install_path))
44
+ end
45
+
46
+ # Clones remote template catalog to the local directory
47
+ def update_shared_catalog_if_needed(templates)
48
+ needs_update = templates.any? {|template| template.type == TemplateDeclarationType::CATALOG_TEMPLATE}
49
+
50
+ return unless needs_update
51
+
52
+ puts('Updating shared generamba-catalog specs...')
53
+
54
+ catalog_local_path = Pathname.new(ENV['HOME'])
55
+ .join(GENERAMBA_HOME_DIR)
56
+ .join(CATALOGS_DIR)
57
+ FileUtils.rm_rf catalog_local_path
58
+ FileUtils.mkdir_p catalog_local_path
59
+
60
+ Git.clone(RAMBLER_CATALOG_REPO, GENERAMBA_CATALOG_NAME, :path => catalog_local_path)
61
+ end
62
+
63
+ # Provides the appropriate strategy for a given template type
64
+ def strategy_for_type(type)
65
+ case type
66
+ when TemplateDeclarationType::LOCAL_TEMPLATE
67
+ return Generamba::LocalInstaller.new
68
+ when TemplateDeclarationType::REMOTE_TEMPLATE
69
+ return Generamba::RemoteInstaller.new
70
+ when TemplateDeclarationType::CATALOG_TEMPLATE
71
+ return Generamba::CatalogInstaller.new
72
+ else
73
+ return nil
74
+ end
75
+ end
76
+ end
77
+ end