generamba 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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