power_stencil 0.3.1
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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +198 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/update_plugin_template +79 -0
- data/doc/builds.md +267 -0
- data/doc/entities.md +964 -0
- data/doc/example_use_cases.md +59 -0
- data/doc/images/power-stencil-entity-build.svg +481 -0
- data/doc/images/power-stencil-entity-creation.svg +375 -0
- data/doc/images/power-stencil-simple-flow.svg +265 -0
- data/doc/plugins.md +169 -0
- data/doc/templates.md +333 -0
- data/etc/base_commands_definition.yml +259 -0
- data/etc/meta_templates/plugin_seed/etc/command_line.yaml +12 -0
- data/etc/meta_templates/plugin_seed/etc/plugin_config.yaml +4 -0
- data/etc/meta_templates/plugin_seed/etc/templates/.git_keep +0 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}.rb.erb +34 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/entity_definitions/{entity}_entity.rb.erb +11 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/plugin_helper.rb.erb +17 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/version.rb.erb +3 -0
- data/etc/meta_templates/plugin_seed/lib/{entity}/{entity}_processor.rb.erb +19 -0
- data/etc/meta_templates/plugin_seed/psplugin_{entity}.gemspec +36 -0
- data/etc/power_stencil.yaml +92 -0
- data/etc/templates/plugin_definition/.gitignore +11 -0
- data/etc/templates/plugin_definition/.rspec +3 -0
- data/etc/templates/plugin_definition/.travis.yml +5 -0
- data/etc/templates/plugin_definition/CODE_OF_CONDUCT.md +74 -0
- data/etc/templates/plugin_definition/Gemfile +6 -0
- data/etc/templates/plugin_definition/LICENSE.txt +21 -0
- data/etc/templates/plugin_definition/README.md +43 -0
- data/etc/templates/plugin_definition/Rakefile +6 -0
- data/etc/templates/plugin_definition/bin/console +14 -0
- data/etc/templates/plugin_definition/bin/setup +8 -0
- data/etc/templates/plugin_definition/etc/command_line.yaml +12 -0
- data/etc/templates/plugin_definition/etc/plugin_config.yaml +4 -0
- data/etc/templates/plugin_definition/etc/templates/.git_keep +1 -0
- data/etc/templates/plugin_definition/lib/{entity}.rb.erb +34 -0
- data/etc/templates/plugin_definition/lib/{entity}/entity_definitions/{entity}_entity.rb.erb +11 -0
- data/etc/templates/plugin_definition/lib/{entity}/plugin_helper.rb.erb +17 -0
- data/etc/templates/plugin_definition/lib/{entity}/version.rb.erb +3 -0
- data/etc/templates/plugin_definition/lib/{entity}/{entity}_processor.rb.erb +19 -0
- data/etc/templates/plugin_definition/psplugin_{entity}.gemspec +36 -0
- data/etc/templates/plugin_definition/spec/spec_helper.rb +14 -0
- data/etc/templates/plugin_definition/spec/{entity}_spec.rb +9 -0
- data/etc/templates/project/.copy_ignore +2 -0
- data/etc/templates/project/.gitignore.erb +6 -0
- data/etc/templates/project/.ps_project/entities/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/entities/README.md +11 -0
- data/etc/templates/project/.ps_project/entity_definitions/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/entity_definitions/README.md +15 -0
- data/etc/templates/project/.ps_project/personal-config.yaml +8 -0
- data/etc/templates/project/.ps_project/plugins/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/templates-templates/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/templates-templates/README.md +13 -0
- data/etc/templates/project/.ps_project/user_entities/.gitkeep +0 -0
- data/etc/templates/project/.ps_project/user_entities/README.md +12 -0
- data/etc/templates/project/.ps_project/versioned-config.yaml +6 -0
- data/etc/templates/simple_exec/main.sh +4 -0
- data/exe/power_stencil +28 -0
- data/lib/power_stencil.rb +53 -0
- data/lib/power_stencil/command_processors/build.rb +43 -0
- data/lib/power_stencil/command_processors/check.rb +35 -0
- data/lib/power_stencil/command_processors/create.rb +70 -0
- data/lib/power_stencil/command_processors/delete.rb +38 -0
- data/lib/power_stencil/command_processors/edit.rb +35 -0
- data/lib/power_stencil/command_processors/entity_helper.rb +105 -0
- data/lib/power_stencil/command_processors/get.rb +22 -0
- data/lib/power_stencil/command_processors/info.rb +41 -0
- data/lib/power_stencil/command_processors/init.rb +47 -0
- data/lib/power_stencil/command_processors/new_plugin.rb +31 -0
- data/lib/power_stencil/command_processors/root.rb +27 -0
- data/lib/power_stencil/command_processors/shell.rb +37 -0
- data/lib/power_stencil/command_processors/trace_helper.rb +20 -0
- data/lib/power_stencil/dsl/base.rb +24 -0
- data/lib/power_stencil/dsl/entities.rb +46 -0
- data/lib/power_stencil/dsl/plugin_generation.rb +17 -0
- data/lib/power_stencil/engine/base.rb +50 -0
- data/lib/power_stencil/engine/build_handling.rb +77 -0
- data/lib/power_stencil/engine/directory_processor.rb +111 -0
- data/lib/power_stencil/engine/entities_definitions.rb +42 -0
- data/lib/power_stencil/engine/entities_handling.rb +76 -0
- data/lib/power_stencil/engine/entity_engine.rb +20 -0
- data/lib/power_stencil/engine/init_engine.rb +18 -0
- data/lib/power_stencil/engine/project_engine.rb +75 -0
- data/lib/power_stencil/engine/renderers/erb.rb +21 -0
- data/lib/power_stencil/error.rb +20 -0
- data/lib/power_stencil/initializer.rb +87 -0
- data/lib/power_stencil/plugins/base.rb +54 -0
- data/lib/power_stencil/plugins/capabilities.rb +30 -0
- data/lib/power_stencil/plugins/command_line.rb +27 -0
- data/lib/power_stencil/plugins/config.rb +32 -0
- data/lib/power_stencil/plugins/dependencies.rb +32 -0
- data/lib/power_stencil/plugins/gem.rb +57 -0
- data/lib/power_stencil/plugins/require.rb +77 -0
- data/lib/power_stencil/plugins/templates.rb +21 -0
- data/lib/power_stencil/project/base.rb +79 -0
- data/lib/power_stencil/project/config.rb +54 -0
- data/lib/power_stencil/project/create.rb +30 -0
- data/lib/power_stencil/project/info.rb +72 -0
- data/lib/power_stencil/project/paths.rb +119 -0
- data/lib/power_stencil/project/plugins.rb +89 -0
- data/lib/power_stencil/project/proxy.rb +13 -0
- data/lib/power_stencil/project/templates.rb +56 -0
- data/lib/power_stencil/project/versioning.rb +29 -0
- data/lib/power_stencil/system_entity_definitions/all.rb +14 -0
- data/lib/power_stencil/system_entity_definitions/buildable.rb +23 -0
- data/lib/power_stencil/system_entity_definitions/entity_override.rb +8 -0
- data/lib/power_stencil/system_entity_definitions/entity_project_common.rb +33 -0
- data/lib/power_stencil/system_entity_definitions/has_associated_files.rb +13 -0
- data/lib/power_stencil/system_entity_definitions/non_persistent.rb +14 -0
- data/lib/power_stencil/system_entity_definitions/plugin.rb +17 -0
- data/lib/power_stencil/system_entity_definitions/process_descriptor.rb +15 -0
- data/lib/power_stencil/system_entity_definitions/project_config.rb +24 -0
- data/lib/power_stencil/system_entity_definitions/project_entity.rb +16 -0
- data/lib/power_stencil/system_entity_definitions/simple_exec.rb +47 -0
- data/lib/power_stencil/utils/directory_processor.rb +54 -0
- data/lib/power_stencil/utils/file_edit.rb +87 -0
- data/lib/power_stencil/utils/file_helper.rb +56 -0
- data/lib/power_stencil/utils/gem_utils.rb +13 -0
- data/lib/power_stencil/utils/secure_require.rb +26 -0
- data/lib/power_stencil/utils/semantic_version.rb +128 -0
- data/lib/power_stencil/version.rb +3 -0
- data/power_stencil.gemspec +32 -0
- metadata +287 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module SystemEntityDefinitions
|
|
3
|
+
|
|
4
|
+
module EntityProjectCommon
|
|
5
|
+
|
|
6
|
+
def save(uri = source_uri, force_files_generation: false)
|
|
7
|
+
super(uri)
|
|
8
|
+
unless PowerStencil.project.entity_type_templates[type].nil?
|
|
9
|
+
PowerStencil.project.generate_entity_dir_for_entity self, force: force_files_generation
|
|
10
|
+
end
|
|
11
|
+
self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def delete(force_files_deletion: false)
|
|
15
|
+
unless PowerStencil.project.entity_type_templates[type].nil?
|
|
16
|
+
PowerStencil.project.delete_entity_dir_for_entity self, force: force_files_deletion
|
|
17
|
+
end
|
|
18
|
+
super()
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def buildable_by
|
|
23
|
+
self.class.buildable_by
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def buildable?
|
|
27
|
+
self.class.buildable?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module SystemEntityDefinitions
|
|
3
|
+
|
|
4
|
+
class Plugin < PowerStencil::SystemEntityDefinitions::ProjectEntity
|
|
5
|
+
|
|
6
|
+
include PowerStencil::SystemEntityDefinitions::NonPersistent
|
|
7
|
+
|
|
8
|
+
DOC = 'A system class not to be used'
|
|
9
|
+
|
|
10
|
+
entity_type :plugin_definition
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module SystemEntityDefinitions
|
|
3
|
+
|
|
4
|
+
class ProcessDescriptor < PowerStencil::SystemEntityDefinitions::ProjectEntity
|
|
5
|
+
|
|
6
|
+
DOC = 'Generic description of a process'
|
|
7
|
+
|
|
8
|
+
entity_type :process_descriptor
|
|
9
|
+
|
|
10
|
+
field :process, :not_null
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module SystemEntityDefinitions
|
|
3
|
+
|
|
4
|
+
class ProjectConfig < PowerStencil::SystemEntityDefinitions::ProjectEntity
|
|
5
|
+
|
|
6
|
+
include PowerStencil::SystemEntityDefinitions::NonPersistent
|
|
7
|
+
|
|
8
|
+
DOC = 'A system singleton read-only entity holding runtime PowerStencil configuration'
|
|
9
|
+
|
|
10
|
+
entity_type :project_config
|
|
11
|
+
|
|
12
|
+
field_reader :simulate, :debug
|
|
13
|
+
|
|
14
|
+
def initialize(fields: {}, universe: nil)
|
|
15
|
+
super
|
|
16
|
+
self.name = 'Project Config'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module SystemEntityDefinitions
|
|
3
|
+
|
|
4
|
+
class ProjectEntity < UniverseCompiler::Entity::Base
|
|
5
|
+
|
|
6
|
+
extend PowerStencil::SystemEntityDefinitions::Buildable
|
|
7
|
+
include PowerStencil::SystemEntityDefinitions::EntityProjectCommon
|
|
8
|
+
|
|
9
|
+
entity_type :base_entity
|
|
10
|
+
|
|
11
|
+
field :description
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module SystemEntityDefinitions
|
|
3
|
+
|
|
4
|
+
class SimpleExec < PowerStencil::SystemEntityDefinitions::ProjectEntity
|
|
5
|
+
|
|
6
|
+
include PowerStencil::SystemEntityDefinitions::HasAssociatedFiles
|
|
7
|
+
|
|
8
|
+
DOC = 'Describes a simple process to be called after source files have been rendered'.freeze
|
|
9
|
+
|
|
10
|
+
entity_type :simple_exec
|
|
11
|
+
|
|
12
|
+
buildable_by ''
|
|
13
|
+
|
|
14
|
+
has_one :process_descriptor, name: :post_process
|
|
15
|
+
not_null :post_process
|
|
16
|
+
|
|
17
|
+
def valid?(raise_error: false)
|
|
18
|
+
unless super(raise_error: false)
|
|
19
|
+
if self.post_process.nil?
|
|
20
|
+
self.post_process = PowerStencil.project.engine.new_entity universe, :process_descriptor, fields: {
|
|
21
|
+
name: "simple_exec_#{name}.process",
|
|
22
|
+
process: './main.sh'
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
super(raise_error: raise_error)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def save(uri = source_uri, force_files_generation: false)
|
|
30
|
+
valid?
|
|
31
|
+
self.post_process.save
|
|
32
|
+
super(uri, force_files_generation: force_files_generation)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete(force_files_deletion: false)
|
|
36
|
+
super
|
|
37
|
+
if self.post_process.name == "simple_exec_#{name}.process"
|
|
38
|
+
self.post_process.delete
|
|
39
|
+
end
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module Utils
|
|
3
|
+
|
|
4
|
+
module DirectoryProcessor
|
|
5
|
+
|
|
6
|
+
def process_directory(source: nil,
|
|
7
|
+
destination: nil,
|
|
8
|
+
ignore_files_pattern: DirGlobIgnore::IgnoreFileLists::DEFAULT_FILE_NAME)
|
|
9
|
+
raise PowerStencil::Error, 'Source and destination have to be different' if source == destination
|
|
10
|
+
source = check_source_dir source
|
|
11
|
+
destination = check_destination_dir destination
|
|
12
|
+
# Dir.glob_with_ignore_file ignore_file, base_dir, *glob_args, &block
|
|
13
|
+
file_pattern = "#{source}/**/*"
|
|
14
|
+
res = {}
|
|
15
|
+
Dir.glob_with_ignore_file ignore_files_pattern, source, file_pattern, File::FNM_DOTMATCH do |original_file|
|
|
16
|
+
logger.debug "Processing '#{original_file}'"
|
|
17
|
+
res[original_file] = destination_file(original_file, source, destination)
|
|
18
|
+
if block_given?
|
|
19
|
+
yield original_file, destination_file(original_file, source, destination)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
res
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def destination_file(original_file, source, destination)
|
|
28
|
+
original_file.gsub /^#{source}/, destination
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def check_source_dir(source)
|
|
32
|
+
raise PowerStencil::Error, 'Please specify a source directory !' if source.nil?
|
|
33
|
+
source = File.expand_path source
|
|
34
|
+
raise PowerStencil::Error, "Source directory '#{source}' does not exist !" unless File.exist? source
|
|
35
|
+
source
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def check_destination_dir(destination)
|
|
39
|
+
raise PowerStencil::Error, 'Please specify a destination directory !' if destination.nil?
|
|
40
|
+
destination = File.expand_path destination
|
|
41
|
+
if File.exist? destination
|
|
42
|
+
raise PowerStencil::Error, "Destination '#{destination}' is not a directory !" unless File.directory? destination
|
|
43
|
+
end
|
|
44
|
+
# raise PowerStencil::Error, "Destination '#{destination}' is not a directory !" unless File.directory? destination
|
|
45
|
+
# raise PowerStencil::Error, "Destination directory '#{destination}' already exists !" if File.exist? destination
|
|
46
|
+
destination
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
module PowerStencil
|
|
5
|
+
module Utils
|
|
6
|
+
|
|
7
|
+
module FileEdit
|
|
8
|
+
|
|
9
|
+
include Climatic::Proxy
|
|
10
|
+
|
|
11
|
+
EDITOR_ENVIRONMENT_VARIABLE = 'EDITOR'
|
|
12
|
+
LAST_EDITED_FILE = '/tmp/last-failed-edit.yaml'
|
|
13
|
+
|
|
14
|
+
attr_writer :editor, :nb_max_edit_retries
|
|
15
|
+
|
|
16
|
+
def editor
|
|
17
|
+
default = config[:editor] || ENV[EDITOR_ENVIRONMENT_VARIABLE]
|
|
18
|
+
@editor ||= default
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def nb_max_edit_retries
|
|
22
|
+
@nb_max_edit_retries ||= config[:max_file_edit_retry_times]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def securely_edit_entity(entity, &modifications_validation_block)
|
|
26
|
+
initial_uri = entity.source_uri
|
|
27
|
+
modified_entity = nil
|
|
28
|
+
Tempfile.create([entity.type.to_s, entity.name.to_s]) do |tmpfile|
|
|
29
|
+
tmpfile.puts entity.to_yaml
|
|
30
|
+
tmpfile.flush
|
|
31
|
+
securely_edit_file(tmpfile, &modifications_validation_block)
|
|
32
|
+
modified_entity = UniverseCompiler::Entity::Persistence.load tmpfile
|
|
33
|
+
modified_entity.source_uri = initial_uri
|
|
34
|
+
end
|
|
35
|
+
return modified_entity
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def securely_edit_file(file, &modifications_validation_block)
|
|
39
|
+
unless File.exists? file and File.writable? file
|
|
40
|
+
raise PowerStencil::Error, "Cannot edit file '#{file}' !"
|
|
41
|
+
end
|
|
42
|
+
ext = File.extname file
|
|
43
|
+
base = File.basename file, ext
|
|
44
|
+
tmp_file_path = Tempfile.new([base, ext]).path
|
|
45
|
+
retry_count = 1
|
|
46
|
+
begin
|
|
47
|
+
FileUtils.copy file, tmp_file_path if retry_count == 1
|
|
48
|
+
edit_file tmp_file_path
|
|
49
|
+
if block_given?
|
|
50
|
+
unless modifications_validation_block.call tmp_file_path, file
|
|
51
|
+
raise PowerStencil::Error, "Your modifications to '#{file}' are invalid !"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
FileUtils.copy tmp_file_path, file
|
|
55
|
+
logger.info "File '#{file}' updated successfully."
|
|
56
|
+
file
|
|
57
|
+
rescue StandardError => e
|
|
58
|
+
retry_count += 1
|
|
59
|
+
if retry_count > nb_max_edit_retries
|
|
60
|
+
logger.error "Your modifications are kept in '#{LAST_EDITED_FILE}' as it was invalid !"
|
|
61
|
+
begin
|
|
62
|
+
FileUtils.copy tmp_file_path, LAST_EDITED_FILE
|
|
63
|
+
rescue => ue
|
|
64
|
+
logger.error 'Cannot keep your modifications !'
|
|
65
|
+
logger.debug PowerStencil::Error.report_error(ue)
|
|
66
|
+
end
|
|
67
|
+
else
|
|
68
|
+
retry
|
|
69
|
+
end
|
|
70
|
+
raise e
|
|
71
|
+
ensure
|
|
72
|
+
File.unlink tmp_file_path
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def edit_file(file)
|
|
79
|
+
raise PowerStencil::Error, 'No editor specified' if editor.nil?
|
|
80
|
+
logger.debug "Editing file '#{file}', using editor '#{editor}'"
|
|
81
|
+
system "#{editor} '#{file}'"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module Utils
|
|
3
|
+
|
|
4
|
+
module FileHelper
|
|
5
|
+
|
|
6
|
+
def find_recursively_in_path(dir_or_file, from_dir)
|
|
7
|
+
raise PowerStencil::Error, "Invalid directory '#{from_dir}'" unless Dir.exist?(from_dir) and File.readable?(from_dir)
|
|
8
|
+
|
|
9
|
+
candidate = File.join from_dir, dir_or_file
|
|
10
|
+
|
|
11
|
+
if Dir.exists? candidate or File.exist? candidate
|
|
12
|
+
if File.readable? candidate and File.writable? candidate
|
|
13
|
+
candidate
|
|
14
|
+
else
|
|
15
|
+
PowerStencil.logger.warn "Humm, found something: '#{candidate}', but with wrong access rights."
|
|
16
|
+
nil
|
|
17
|
+
end
|
|
18
|
+
else
|
|
19
|
+
next_dir = File.expand_path '..', from_dir
|
|
20
|
+
if next_dir == from_dir
|
|
21
|
+
PowerStencil.logger.info "Didn't find any trace of '#{dir_or_file}'... :("
|
|
22
|
+
nil
|
|
23
|
+
else
|
|
24
|
+
find_recursively_in_path dir_or_file, next_dir
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def yaml_file_to_hash(file_name)
|
|
31
|
+
raw_content = File.read file_name
|
|
32
|
+
res = YAML.load raw_content
|
|
33
|
+
if res
|
|
34
|
+
Hash[res.map { |k, v| [k, v] }]
|
|
35
|
+
else
|
|
36
|
+
raise PowerStencil::Error, "Invalid file content for '#{file_name}'" unless raw_content.empty?
|
|
37
|
+
[]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def timestamped_uniq_dir(seed, start_time)
|
|
42
|
+
uniq_dir = timestamp start_time
|
|
43
|
+
uniq_dir += "-#{seed}" unless seed.nil?
|
|
44
|
+
uniq_dir
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def timestamp(timedate)
|
|
48
|
+
timedate.strftime '%Y%m%d-%H%M-%S%L'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module Utils
|
|
3
|
+
|
|
4
|
+
module SecureRequire
|
|
5
|
+
|
|
6
|
+
def securely_require(ruby_source_file, fail_on_error: false)
|
|
7
|
+
PowerStencil.logger.debug "Securely requiring Ruby source file '#{ruby_source_file}'..."
|
|
8
|
+
require ruby_source_file
|
|
9
|
+
yield if block_given?
|
|
10
|
+
rescue => e
|
|
11
|
+
PowerStencil.logger.debug PowerStencil::Error.report_error(e)
|
|
12
|
+
msg = "Could not require Ruby source file '#{ruby_source_file}' !"
|
|
13
|
+
if fail_on_error
|
|
14
|
+
msg << ' Aborting !'
|
|
15
|
+
PowerStencil.logger.error msg
|
|
16
|
+
raise PowerStencil::Error, "Invalid Ruby source file: '#{ruby_source_file}' !"
|
|
17
|
+
else
|
|
18
|
+
msg << " (#{e.message})"
|
|
19
|
+
msg << ' Ignoring...'
|
|
20
|
+
PowerStencil.logger.warn msg
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
module PowerStencil
|
|
2
|
+
module Utils
|
|
3
|
+
|
|
4
|
+
class SemanticVersion
|
|
5
|
+
|
|
6
|
+
include Comparable
|
|
7
|
+
|
|
8
|
+
MANDATORY_LEVELS = %i(major minor patch).freeze
|
|
9
|
+
OPTIONAL_LEVEL = :extra
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def valid_version?(version, raise_error: false)
|
|
13
|
+
new version
|
|
14
|
+
true
|
|
15
|
+
rescue => e
|
|
16
|
+
raise e if raise_error
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def initialize(semantic_version)
|
|
22
|
+
@version = analyze_semantic_version semantic_version
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def <=>(other)
|
|
26
|
+
other_hash = analyze_semantic_version other
|
|
27
|
+
MANDATORY_LEVELS.each do |level|
|
|
28
|
+
r = @version[level] <=> other_hash[level]
|
|
29
|
+
return r unless r == 0
|
|
30
|
+
end
|
|
31
|
+
if @version[OPTIONAL_LEVEL].nil? and other_hash[OPTIONAL_LEVEL]
|
|
32
|
+
return 1
|
|
33
|
+
end
|
|
34
|
+
unless @version[OPTIONAL_LEVEL].nil?
|
|
35
|
+
return -1 if other_hash[OPTIONAL_LEVEL].nil?
|
|
36
|
+
return @version[OPTIONAL_LEVEL] <=> other_hash[OPTIONAL_LEVEL]
|
|
37
|
+
end
|
|
38
|
+
0
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def increment(level = :patch)
|
|
42
|
+
raise PowerStencil::Error, "'#{level}' is not a valid level !" unless MANDATORY_LEVELS.include? level
|
|
43
|
+
h = self.to_hash
|
|
44
|
+
increment_hash(h, level)
|
|
45
|
+
self.class.new h
|
|
46
|
+
end
|
|
47
|
+
alias :succ :increment
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def increment!(level = :patch)
|
|
51
|
+
raise PowerStencil::Error, "'#{level}' is not a valid level !" unless MANDATORY_LEVELS.include? level
|
|
52
|
+
increment_hash(@version, level)
|
|
53
|
+
self
|
|
54
|
+
end
|
|
55
|
+
alias :succ! :increment!
|
|
56
|
+
|
|
57
|
+
def to_s
|
|
58
|
+
hash_to_version_string @version
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def to_hash
|
|
62
|
+
@version.dup
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def increment_hash(hash, level)
|
|
68
|
+
hash[level] = hash[level].succ
|
|
69
|
+
hash[:patch] = 0 if level == :minor
|
|
70
|
+
if level == :major
|
|
71
|
+
hash[:minor] = 0
|
|
72
|
+
hash[:patch] = 0
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def analyze_semantic_version(semantic_version)
|
|
77
|
+
case semantic_version
|
|
78
|
+
when String
|
|
79
|
+
version_string_to_hash semantic_version
|
|
80
|
+
when SemanticVersion
|
|
81
|
+
semantic_version.to_hash
|
|
82
|
+
when Hash
|
|
83
|
+
MANDATORY_LEVELS.each do |level|
|
|
84
|
+
raise_analysis_error semantic_version unless semantic_version.keys.include? level
|
|
85
|
+
raise_analysis_error semantic_version unless semantic_version[level].is_a? Fixnum
|
|
86
|
+
end
|
|
87
|
+
semantic_version.dup
|
|
88
|
+
else
|
|
89
|
+
raise_analysis_error semantic_version
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def raise_analysis_error(obj)
|
|
94
|
+
raise PowerStencil::Error, "#{obj.class} cannot be used as semantic version !"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def hash_to_version_string(hash)
|
|
99
|
+
version_string = MANDATORY_LEVELS.map {|l| hash[l]}.join '.'
|
|
100
|
+
unless hash[OPTIONAL_LEVEL].nil?
|
|
101
|
+
version_string << "-#{hash[OPTIONAL_LEVEL]}"
|
|
102
|
+
end
|
|
103
|
+
version_string
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def version_string_to_hash(version_string)
|
|
107
|
+
res = {}
|
|
108
|
+
begin
|
|
109
|
+
version_string.match(/^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<extra>.*))*$/) do |md|
|
|
110
|
+
res = {
|
|
111
|
+
major: md['major'].to_i,
|
|
112
|
+
minor: md['minor'].to_i,
|
|
113
|
+
patch: md['patch'].to_i,
|
|
114
|
+
extra: md['extra'],
|
|
115
|
+
}
|
|
116
|
+
return res
|
|
117
|
+
end
|
|
118
|
+
raise
|
|
119
|
+
rescue
|
|
120
|
+
raise PowerStencil::Error, "Invalid semantic version '#{version_string}' !"
|
|
121
|
+
end
|
|
122
|
+
res
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
end
|
|
128
|
+
end
|