power_stencil 0.6.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +2 -0
- data/README.md +3 -7
- data/doc/builds.md +10 -1
- data/doc/entities.md +59 -50
- data/doc/images/power-stencil-entity-creation.svg +247 -114
- data/doc/plugins.md +1 -0
- data/doc/templates.md +23 -18
- data/etc/base_commands_definition.yml +14 -0
- data/etc/power_stencil.yaml +7 -1
- data/etc/templates/project/.zzzgitignore.erb +8 -3
- data/lib/power_stencil.rb +1 -0
- data/lib/power_stencil/command_processors/build.rb +15 -2
- data/lib/power_stencil/command_processors/check.rb +12 -0
- data/lib/power_stencil/command_processors/create.rb +6 -5
- data/lib/power_stencil/command_processors/delete.rb +23 -15
- data/lib/power_stencil/command_processors/edit.rb +4 -2
- data/lib/power_stencil/command_processors/plugin.rb +21 -6
- data/lib/power_stencil/command_processors/shell.rb +10 -3
- data/lib/power_stencil/dsl/entities.rb +0 -16
- data/lib/power_stencil/engine/entities_definitions.rb +16 -7
- data/lib/power_stencil/engine/entities_handling.rb +1 -1
- data/lib/power_stencil/engine/project_engine.rb +6 -10
- data/lib/power_stencil/initializer.rb +4 -7
- data/lib/power_stencil/plugins/entity_definitions.rb +15 -0
- data/lib/power_stencil/plugins/require.rb +1 -0
- data/lib/power_stencil/plugins/templates.rb +3 -3
- data/lib/power_stencil/project/base.rb +24 -9
- data/lib/power_stencil/project/create.rb +23 -2
- data/lib/power_stencil/project/git.rb +75 -0
- data/lib/power_stencil/project/info.rb +14 -1
- data/lib/power_stencil/project/paths.rb +22 -6
- data/lib/power_stencil/project/plugins.rb +1 -1
- data/lib/power_stencil/project/templates.rb +15 -22
- data/lib/power_stencil/system_entity_definitions/all.rb +2 -1
- data/lib/power_stencil/system_entity_definitions/buildable.rb +1 -1
- data/lib/power_stencil/system_entity_definitions/entity_override.rb +6 -0
- data/lib/power_stencil/system_entity_definitions/entity_project_common.rb +13 -5
- data/lib/power_stencil/system_entity_definitions/{has_associated_files.rb → entity_templates.rb} +2 -2
- data/lib/power_stencil/system_entity_definitions/project_config.rb +1 -1
- data/lib/power_stencil/system_entity_definitions/project_entity.rb +7 -0
- data/lib/power_stencil/system_entity_definitions/simple_exec.rb +3 -3
- data/lib/power_stencil/system_entity_definitions/source_provider.rb +15 -0
- data/lib/power_stencil/version.rb +1 -1
- data/power_stencil.gemspec +1 -0
- metadata +20 -4
@@ -7,7 +7,7 @@ module PowerStencil
|
|
7
7
|
|
8
8
|
include PowerStencil::Utils::SecureRequire
|
9
9
|
|
10
|
-
def require_definition_files(files_or_dirs)
|
10
|
+
def require_definition_files(files_or_dirs, source)
|
11
11
|
required_files = []
|
12
12
|
files_or_dirs.each do |file_or_dir|
|
13
13
|
if File.directory? file_or_dir and File.readable? file_or_dir
|
@@ -21,21 +21,30 @@ module PowerStencil
|
|
21
21
|
next
|
22
22
|
end
|
23
23
|
# This is a ruby library or there is something wrong
|
24
|
-
|
25
|
-
|
26
|
-
# logger.warn "While trying to load definition files, found that '#{file_or_dir}' has a problem. Ignored..."
|
27
|
-
# end
|
24
|
+
securely_require_with_entity_class_detection file_or_dir, source
|
25
|
+
|
28
26
|
end
|
29
|
-
required_files.sort!.each {|file|
|
27
|
+
required_files.sort!.each { |file| securely_require_with_entity_class_detection file, source }
|
30
28
|
required_files
|
31
29
|
end
|
32
30
|
|
33
31
|
private
|
34
32
|
|
35
33
|
def load_system_entities_definition
|
36
|
-
require_definition_files [SYSTEM_ENTITY_DEFINITION_ENTRY_POINT]
|
34
|
+
require_definition_files [SYSTEM_ENTITY_DEFINITION_ENTRY_POINT], PowerStencil
|
37
35
|
end
|
38
36
|
|
37
|
+
def securely_require_with_entity_class_detection(entity_definition_file_path, source)
|
38
|
+
before = PowerStencil::Engine::EntitiesHandling.all_types
|
39
|
+
securely_require entity_definition_file_path, fail_on_error: true
|
40
|
+
after = PowerStencil::Engine::EntitiesHandling.all_types
|
41
|
+
after.reject { |k, _| before.keys.include? k }
|
42
|
+
.each do |_, plugin_entity_class|
|
43
|
+
plugin_entity_class.instance_eval do
|
44
|
+
@entity_type_source_provider = source
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
50
|
end
|
@@ -59,7 +59,7 @@ module PowerStencil
|
|
59
59
|
raise PowerStencil::Error, "Unknown entity type: '#{type}'"
|
60
60
|
end
|
61
61
|
fields[:name] = fields[:name].to_s
|
62
|
-
res = @available_entities_hash[type.to_sym].new fields: fields, universe: work_universe
|
62
|
+
res = @available_entities_hash[type.to_sym].new fields: fields, universe: work_universe, user: user
|
63
63
|
logger.debug "Created new '#{type}': \n#{fields.to_yaml}"
|
64
64
|
work_universe.add res
|
65
65
|
if work_universe == PowerStencil.project.engine.root_universe
|
@@ -36,7 +36,7 @@ module PowerStencil
|
|
36
36
|
if Dir.exist? dir and File.readable? dir
|
37
37
|
logger.info 'Loading project specific entity definitions.'
|
38
38
|
$LOAD_PATH << dir
|
39
|
-
require_definition_files [dir]
|
39
|
+
require_definition_files [dir], project
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -62,24 +62,20 @@ module PowerStencil
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def load_project_entities
|
65
|
-
logger.debug 'Loading project entities - NOT IMPLEMENTED'
|
66
65
|
root_universe.import project.project_entities_path, stop_on_error: false do |new_entity|
|
67
|
-
|
66
|
+
logger.debug "Loaded entity: '#{new_entity.as_path}'"
|
68
67
|
end
|
69
68
|
end
|
70
69
|
|
71
70
|
def load_user_entities
|
72
|
-
logger.debug 'Loading user entities - NOT IMPLEMENTED'
|
73
71
|
root_universe.import project.user_entities_path, stop_on_error: false do |new_entity|
|
74
|
-
|
72
|
+
logger.debug "Loaded unversioned entity: '#{new_entity.as_path}'"
|
73
|
+
new_entity.instance_eval do
|
74
|
+
@is_versioned_entity = false
|
75
|
+
end
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
78
|
-
def process_entity(entity)
|
79
|
-
logger.debug "New entity: '#{entity.name}' (#{entity.type})"
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
79
|
end
|
84
80
|
|
85
81
|
end
|
@@ -8,17 +8,15 @@ module PowerStencil
|
|
8
8
|
|
9
9
|
include Climatic::Proxy
|
10
10
|
|
11
|
+
def name
|
12
|
+
'PowerStencil core'
|
13
|
+
end
|
14
|
+
|
11
15
|
def bootstrap(cmd_line_args = ARGV.dup)
|
12
16
|
setup_climatic cmd_line_args
|
13
17
|
logger.debug 'Starting PowerStencil initialization...'
|
14
18
|
setup_system_processors
|
15
19
|
setup_universe_compiler_logger
|
16
|
-
# @project = try_to_load_project fail_on_error: false
|
17
|
-
begin
|
18
|
-
project.setup_templates_for_entities # unless project.nil?
|
19
|
-
rescue => e
|
20
|
-
logger.debug PowerStencil::Error.report_error e
|
21
|
-
end
|
22
20
|
logger.debug 'PowerStencil initialization complete'
|
23
21
|
end
|
24
22
|
|
@@ -32,7 +30,6 @@ module PowerStencil
|
|
32
30
|
|
33
31
|
def try_to_load_project(fail_on_error: true)
|
34
32
|
PowerStencil::Project::Base.instantiate_from_config config
|
35
|
-
|
36
33
|
end
|
37
34
|
|
38
35
|
def setup_system_processors
|
@@ -6,9 +6,24 @@ module PowerStencil
|
|
6
6
|
def require_plugin_entity_definitions
|
7
7
|
return unless capabilities[:entity_definitions]
|
8
8
|
logger.info "Requiring '#{self.name}' plugin entity definitions..."
|
9
|
+
securely_require_with_entity_class_detection
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def securely_require_with_entity_class_detection
|
16
|
+
before = PowerStencil::Engine::EntitiesHandling.all_types
|
9
17
|
plugin_definition[:entity_definitions].each do |entity_definition_file_path|
|
10
18
|
securely_require entity_definition_file_path, fail_on_error: true
|
11
19
|
end
|
20
|
+
after = PowerStencil::Engine::EntitiesHandling.all_types
|
21
|
+
after.reject { |k, _| before.keys.include? k }.each do |_, plugin_entity_class|
|
22
|
+
plugin = self
|
23
|
+
plugin_entity_class.instance_eval do
|
24
|
+
@entity_type_source_provider = plugin
|
25
|
+
end
|
26
|
+
end
|
12
27
|
end
|
13
28
|
|
14
29
|
end
|
@@ -21,6 +21,7 @@ module PowerStencil
|
|
21
21
|
$LOAD_PATH << plugin_root_path
|
22
22
|
securely_require entry_point_path unless plugin_definition[:plugin_module].nil?
|
23
23
|
rescue LoadError => e
|
24
|
+
@entry_point_path = nil
|
24
25
|
logger.warn "As plugin '#{name}' code is invalid, removing '#{plugin_root_path}' from LOAD_PATH"
|
25
26
|
$LOAD_PATH.delete plugin_root_path
|
26
27
|
end
|
@@ -3,15 +3,15 @@ module PowerStencil
|
|
3
3
|
|
4
4
|
module Templates
|
5
5
|
|
6
|
-
def
|
6
|
+
def register_plugin_templates_templates
|
7
7
|
return unless capabilities[:templates]
|
8
8
|
logger.info "Loading '#{self.name}' plugin templates..."
|
9
9
|
plugin_definition[:templates].each do |templates_path|
|
10
|
-
plugin_templates_path = File.join self.
|
10
|
+
plugin_templates_path = File.join self.plugin_path, templates_path
|
11
11
|
Dir.entries(plugin_templates_path).reject { |e| %w(. ..).include? e }.each do |entry|
|
12
12
|
template_path = File.join(plugin_templates_path, entry)
|
13
13
|
if Dir.exist? template_path
|
14
|
-
project.
|
14
|
+
project.register_template_template_path_for_type entry.to_sym, template_path
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -5,6 +5,7 @@ require 'power_stencil/project/versioning'
|
|
5
5
|
require 'power_stencil/project/info'
|
6
6
|
require 'power_stencil/project/templates'
|
7
7
|
require 'power_stencil/project/plugins'
|
8
|
+
require 'power_stencil/project/git'
|
8
9
|
|
9
10
|
require 'power_stencil/engine/project_engine'
|
10
11
|
require 'power_stencil/engine/entity_engine'
|
@@ -30,40 +31,54 @@ module PowerStencil
|
|
30
31
|
include PowerStencil::Project::Templates
|
31
32
|
include PowerStencil::Project::Plugins
|
32
33
|
include PowerStencil::Project::Info
|
34
|
+
include PowerStencil::Project::Git
|
33
35
|
extend PowerStencil::Project::Create
|
34
36
|
|
35
37
|
attr_reader :engine, :entity_engine
|
36
38
|
|
39
|
+
def name
|
40
|
+
File.dirname project_config_root
|
41
|
+
end
|
42
|
+
|
37
43
|
def initialize(search_from_path: Dir.pwd)
|
38
44
|
initialize_paths search_from_path
|
39
45
|
load_project_specific_config
|
40
46
|
check_project_version
|
41
47
|
bootstrap_plugins
|
42
48
|
build_engines
|
43
|
-
|
44
|
-
|
49
|
+
register_system_templates_templates
|
50
|
+
register_plugins_templates_templates
|
51
|
+
register_project_templates_templates
|
52
|
+
setup_git_tracking
|
45
53
|
end
|
46
54
|
|
47
55
|
private
|
48
56
|
|
49
|
-
def
|
50
|
-
|
57
|
+
def register_plugins_templates_templates
|
58
|
+
plugins.each do |_, plugin|
|
59
|
+
plugin.register_plugin_templates_templates
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def register_project_templates_templates
|
65
|
+
dir = project_templates_templates_path
|
51
66
|
if Dir.exist? dir and File.readable? dir
|
52
67
|
logger.info 'Registering project specific templates.'
|
53
68
|
Dir.entries(dir).each do |potential_entity_type|
|
54
69
|
next if potential_entity_type.match /^\./
|
55
70
|
template_dir = File.join(dir, potential_entity_type)
|
56
71
|
next unless File.directory? template_dir
|
57
|
-
|
72
|
+
register_template_template_path_for_type potential_entity_type.to_sym, template_dir
|
58
73
|
end
|
59
74
|
end
|
60
75
|
end
|
61
76
|
|
62
|
-
def
|
77
|
+
def register_system_templates_templates
|
63
78
|
logger.debug 'Registering system templates'
|
64
79
|
%i(plugin_definition simple_exec).each do |template_name|
|
65
|
-
template_path =
|
66
|
-
|
80
|
+
template_path = system_template_template_path template_name
|
81
|
+
register_template_template_path_for_type template_name, template_path
|
67
82
|
end
|
68
83
|
end
|
69
84
|
|
@@ -76,4 +91,4 @@ module PowerStencil
|
|
76
91
|
end
|
77
92
|
|
78
93
|
end
|
79
|
-
end
|
94
|
+
end
|
@@ -5,6 +5,8 @@ module PowerStencil
|
|
5
5
|
|
6
6
|
module Create
|
7
7
|
|
8
|
+
INITIAL_REPOSITORY_COMMIT_MESSAGE = 'Initial commit for project "%s".'
|
9
|
+
|
8
10
|
include Climatic::Proxy
|
9
11
|
|
10
12
|
def create_project_tree(path, config_directory_name = PowerStencil.config[:default_config_directory_name])
|
@@ -14,14 +16,33 @@ module PowerStencil
|
|
14
16
|
raise PowerStencil::Error, "The directory '#{path}' already contains a PowerStencil project !" unless config[:force]
|
15
17
|
end
|
16
18
|
logger.info "Creating project in '#{path}'..."
|
17
|
-
render_project_template_in
|
19
|
+
render_project_template_in path
|
20
|
+
initialize_git_repository path
|
18
21
|
end
|
19
22
|
|
20
23
|
private
|
21
24
|
|
25
|
+
def initialize_git_repository(repo_path)
|
26
|
+
if config[:'no-git']
|
27
|
+
puts_and_logs 'Do not initialize project git repository as per config request.', logs_as: :debug
|
28
|
+
return
|
29
|
+
end
|
30
|
+
if Dir.exists? File.join(repo_path, '.git')
|
31
|
+
puts_and_logs 'Git repository already exists. Skipping.', logs_as: :debug, check_verbose: false
|
32
|
+
return
|
33
|
+
end
|
34
|
+
puts_and_logs 'Initializing git repository...', logs_as: :debug
|
35
|
+
git = ::Git.init repo_path
|
36
|
+
logger.debug 'Adding all files.'
|
37
|
+
git.add repo_path
|
38
|
+
logger.debug 'Committing initial status'
|
39
|
+
commit_msg = INITIAL_REPOSITORY_COMMIT_MESSAGE % [File.basename(repo_path)]
|
40
|
+
git.commit_all commit_msg
|
41
|
+
end
|
42
|
+
|
22
43
|
def render_project_template_in(new_project_config_path)
|
23
44
|
engine = PowerStencil::Engine::InitEngine.new
|
24
|
-
engine.render_source PowerStencil::Project::Paths.
|
45
|
+
engine.render_source PowerStencil::Project::Paths.project_system_template_template_path, new_project_config_path
|
25
46
|
end
|
26
47
|
|
27
48
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module PowerStencil
|
2
|
+
module Project
|
3
|
+
|
4
|
+
module Git
|
5
|
+
|
6
|
+
include Climatic::Utils::Input
|
7
|
+
|
8
|
+
def track_action_with_git(action_message,
|
9
|
+
user_validation_required: false,
|
10
|
+
validation_message: 'Commit changes ?',
|
11
|
+
show_files_to_commit: false,
|
12
|
+
&block)
|
13
|
+
return yield if git.nil?
|
14
|
+
|
15
|
+
status_before_action = git.status
|
16
|
+
yield
|
17
|
+
status_after_action = git.status
|
18
|
+
|
19
|
+
files_introduced_by_action = status_after_action.untracked.reject { |f| status_before_action.untracked.keys.include? f}
|
20
|
+
files_deleted_by_action = status_after_action.deleted.reject { |f| status_before_action.deleted.keys.include? f}
|
21
|
+
files_modified_by_action = status_after_action.changed.reject { |f| status_before_action.changed.keys.include? f}
|
22
|
+
files_to_commit = [files_introduced_by_action, files_deleted_by_action, files_modified_by_action].map(&:keys).flatten.sort.uniq
|
23
|
+
|
24
|
+
if files_to_commit.empty?
|
25
|
+
puts_and_logs 'Nothing to commit.'
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
if show_files_to_commit
|
30
|
+
header = 'Following file'
|
31
|
+
header << 's' if files_to_commit.count > 1
|
32
|
+
header << ' will be committed:'
|
33
|
+
puts header
|
34
|
+
puts files_to_commit.map { |filename| " - '#{filename}'" }
|
35
|
+
end
|
36
|
+
|
37
|
+
if user_validation_required
|
38
|
+
unless get_user_confirmation(default_choice: 'Yes', prompt: validation_message)
|
39
|
+
puts_and_logs 'Commit cancelled by user.', check_verbose: false
|
40
|
+
return
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
files_to_commit.each { |filename| git.add filename }
|
45
|
+
|
46
|
+
# Verify files to be committed really are
|
47
|
+
files_really_to_be_committed = git.diff.stats[:files].keys.select { |filename| files_to_commit.include? filename }
|
48
|
+
return if files_really_to_be_committed.empty?
|
49
|
+
files_really_to_be_committed.each { |filename| logger.info "File '#{filename}' will be committed" }
|
50
|
+
|
51
|
+
git.commit action_message
|
52
|
+
puts_and_logs 'All changes introduced have been committed.'
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
attr_reader :git
|
58
|
+
|
59
|
+
def setup_git_tracking
|
60
|
+
@git = nil
|
61
|
+
if config[:'no-git']
|
62
|
+
logger.debug "Won't track any changes with git as per config request!"
|
63
|
+
return
|
64
|
+
end
|
65
|
+
@git = ::Git.open(self.project_root, :log => PowerStencil.logger)
|
66
|
+
logger.debug 'Following project changes with git'
|
67
|
+
rescue => e
|
68
|
+
logger.debug PowerStencil::Error.report_error(e)
|
69
|
+
logger.warn 'This project is not managed by git'
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -60,7 +60,20 @@ module PowerStencil
|
|
60
60
|
.sort{ |a,b| a.first <=> b.first }
|
61
61
|
.each do |type, klass|
|
62
62
|
msg = "Type '#{type}' --> #{klass}"
|
63
|
-
|
63
|
+
|
64
|
+
source_provider = klass.entity_type_source_provider
|
65
|
+
source_provider_display = if source_provider == PowerStencil
|
66
|
+
"'#{source_provider.name}'"
|
67
|
+
elsif source_provider == self
|
68
|
+
"project '#{source_provider.name}'"
|
69
|
+
elsif source_provider.is_a? PowerStencil::Plugins::Base
|
70
|
+
"plugin '#{source_provider.name}'"
|
71
|
+
else
|
72
|
+
raise PowerStencil::Error, "Unidentified source provider for #{klass} !"
|
73
|
+
end
|
74
|
+
|
75
|
+
msg << " (provided by #{source_provider_display})"
|
76
|
+
msg << " template-template path: '#{entity_type_templates_templates[type]}'" unless entity_type_templates_templates[type].nil?
|
64
77
|
report << msg
|
65
78
|
end
|
66
79
|
report
|
@@ -7,12 +7,12 @@ module PowerStencil
|
|
7
7
|
|
8
8
|
attr_reader :project_config_root, :started_from
|
9
9
|
|
10
|
-
def self.
|
10
|
+
def self.system_templates_templates_path
|
11
11
|
File.expand_path File.join('..', '..', '..', '..', 'etc', 'templates'), __FILE__
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.
|
15
|
-
File.join
|
14
|
+
def self.project_system_template_template_path
|
15
|
+
File.join system_templates_templates_path, 'project'
|
16
16
|
end
|
17
17
|
|
18
18
|
def build_run_path(seed)
|
@@ -31,8 +31,8 @@ module PowerStencil
|
|
31
31
|
File.join project_root, PowerStencil.config[:project_build_root_directory_name]
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
File.join PowerStencil::Project::Paths.
|
34
|
+
def system_template_template_path(entity_type)
|
35
|
+
File.join PowerStencil::Project::Paths.system_templates_templates_path, entity_type.to_s
|
36
36
|
end
|
37
37
|
|
38
38
|
def project_local_plugins_path
|
@@ -43,10 +43,26 @@ module PowerStencil
|
|
43
43
|
File.join project_local_plugins_path, plugin_name
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
46
|
+
def project_templates_templates_path
|
47
47
|
File.join project_config_root, PowerStencil.config[:project_templates_directory_name]
|
48
48
|
end
|
49
49
|
|
50
|
+
def entities_template_path
|
51
|
+
File.join project_root, PowerStencil.config[:versioned_entities_templates_directory_name]
|
52
|
+
end
|
53
|
+
|
54
|
+
def user_entities_template_path
|
55
|
+
File.join project_root, PowerStencil.config[:unversioned_user_entities_templates_directory_name]
|
56
|
+
end
|
57
|
+
|
58
|
+
def entity_template_path(entity)
|
59
|
+
if entity.is_versioned_entity?
|
60
|
+
File.join entities_template_path, entity.type.to_s, entity.name
|
61
|
+
else
|
62
|
+
File.join user_entities_template_path, entity.type.to_s, entity.name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
50
66
|
def project_entity_definitions_path
|
51
67
|
File.join project_config_root, PowerStencil.config[:project_entity_definitions_directory_name]
|
52
68
|
end
|