avm 0.4.0 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a5a8832847c76afcae4e76ef3e8f7d1391d7cfb0b13788c3dc7273f9ef879f1
4
- data.tar.gz: 0b89bd147edb92e0e3e4d158d16f0995ef41f0544a680beb053f9fa55b96a282
3
+ metadata.gz: c21e54d17440b61336b3345c8c6f2db32b0d2d31f6f9d56f78894d4f01bbb3c7
4
+ data.tar.gz: 29604235a823f781751eaf5031b967a1cf01c5d6c14e194c09e7bfaaba8c2043
5
5
  SHA512:
6
- metadata.gz: a70af189af9aee66a693706ba031e5eb7c6d4c8533144099f325dfe2b88b9ef08daae16de8d2f09857f194816d653d3669527d6bc9c07d173566c9ab9121c3f6
7
- data.tar.gz: d66a1741ec6295f54166a2007a4d168eddd4e7de30f538f87329067b580faf2572514d99302bb467e0b408dfe1a44dd54a9e4e2abaaed0292b3a7ba69bb02b95
6
+ metadata.gz: a3240b4fafbfedcd68581fec71de2099906e599df3adb4f64d4bd66b4ced66582a02ced5db16d47c91ed78eb580daea910c44554d9abfef10ab3b308ff160ab2
7
+ data.tar.gz: 1104ec38c87bc15499ad0cd3d37ddd9c6ad0075d1c286ecb514a142d62f329e9c83035f23223788a5d5acb41a769e13f394180d84b80591a5035e347107de153
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/data/instance/unit'
4
+
5
+ module Avm
6
+ module Data
7
+ module Instance
8
+ class FilesUnit < ::Avm::Data::Instance::Unit
9
+ EXTENSION = '.tar.gz'
10
+
11
+ attr_reader :fs_path_subpath
12
+
13
+ def initialize(instance, fs_path_subpath)
14
+ super(instance)
15
+ @fs_path_subpath = fs_path_subpath
16
+ end
17
+
18
+ before_load :clear_files
19
+
20
+ def files_path
21
+ ::File.join(instance.read_entry(::Avm::Instances::EntryKeys::FS_PATH), fs_path_subpath)
22
+ end
23
+
24
+ def dump_command
25
+ instance.host_env.command('tar', '-czf', '-', '-C', files_path, '.')
26
+ end
27
+
28
+ def load_command
29
+ instance.host_env.command('tar', '-xzf', '-', '-C', files_path)
30
+ end
31
+
32
+ def clear_files
33
+ infom "Removing all files under #{files_path}..."
34
+ instance.host_env.command('mkdir', '-p', files_path).execute!
35
+ instance.host_env.command('find', files_path, '-mindepth', 1, '-delete').execute!
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/data/package'
4
+
5
+ module Avm
6
+ module Data
7
+ module Instance
8
+ class Package < ::Avm::Data::Package
9
+ attr_reader :instance
10
+
11
+ def initialize(instance, options = {})
12
+ @instance = instance
13
+ super options
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/data/unit'
4
+
5
+ module Avm
6
+ module Data
7
+ module Instance
8
+ class Unit < ::Avm::Data::Unit
9
+ attr_reader :instance
10
+
11
+ def initialize(instance)
12
+ @instance = instance
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/require_sub'
4
+ ::EacRubyUtils.require_sub(__FILE__)
5
+
6
+ module Avm
7
+ module Data
8
+ module Instance
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/tools/core_ext'
4
+ require 'avm/files/rotate'
5
+ require 'minitar'
6
+
7
+ module Avm
8
+ module Data
9
+ class Package
10
+ class Dump
11
+ enable_speaker
12
+ enable_listable
13
+
14
+ DEFAULT_EXPIRE_TIME = 1.day
15
+ DEFAULT_FILE_EXTENSION = '.tar'
16
+
17
+ attr_reader :package, :data_file_path, :existing
18
+
19
+ lists.add_string :existing, :denied, :overwrite, :rotate, :rotate_expired
20
+
21
+ def initialize(package, data_file_path, options = {})
22
+ @package = package
23
+ @data_file_path = data_file_path
24
+ options = options.to_options_consumer
25
+ @existing, @expire_time = options.consume(:existing, :expire_time)
26
+ options.validate
27
+ self.class.lists.existing.value_validate!(@existing)
28
+ end
29
+
30
+ def runnable?
31
+ cannot_run_reason.blank?
32
+ end
33
+
34
+ def cannot_run_reason
35
+ return nil if !data_file_exist? ||
36
+ [EXISTING_OVERWRITE, EXISTING_ROTATE].include?(existing)
37
+
38
+ if existing == EXISTING_DENIED
39
+ 'Data exist and overwriting is denied'
40
+ elsif existing == EXISTING_ROTATE_EXPIRED && !data_file_expired?
41
+ 'Data exist and yet is not expired'
42
+ end
43
+ end
44
+
45
+ def run
46
+ raise "Cannot run: #{cannot_run_reason}" unless runnable?
47
+
48
+ build_dir = dump_units_to_build_directory
49
+ package_file = create_package_file(build_dir)
50
+ rotate
51
+ move_download_to_final_dest(package_file)
52
+ end
53
+
54
+ def data_file_exist?
55
+ ::File.exist?(data_file_path)
56
+ end
57
+
58
+ def data_file_time
59
+ data_file_exist? ? ::Time.now - ::File.mtime(data_file_path) : nil
60
+ end
61
+
62
+ def data_file_expired?
63
+ data_file_time.if_present(false) { |v| v >= expire_time }
64
+ end
65
+
66
+ def expire_time
67
+ @expire_time || DEFAULT_EXPIRE_TIME
68
+ end
69
+
70
+ private
71
+
72
+ def download
73
+ infom 'Downloading dump...'
74
+ download_path = find_download_path
75
+ dump_command.system!(output_file: download_path)
76
+ fatal_error "File \"#{download_path}\" not saved" unless ::File.exist?(download_path)
77
+ fatal_error "File \"#{download_path}\" is empty" if ::File.zero?(download_path)
78
+ download_path
79
+ end
80
+
81
+ def move_download_to_final_dest(download_path)
82
+ ::FileUtils.mkdir_p(::File.dirname(data_file_path))
83
+ ::FileUtils.mv(download_path, data_file_path)
84
+ end
85
+
86
+ def rotate
87
+ return unless data_file_exist?
88
+ return unless existing == EXISTING_ROTATE
89
+
90
+ infom "Rotating \"#{data_file_path}\"..."
91
+ ::Avm::Files::Rotate.new(data_file_path).run
92
+ end
93
+
94
+ def new_build_path
95
+ f = ::Tempfile.new(self.class.name.parameterize + '-download')
96
+ path = f.path
97
+ f.close
98
+ f.unlink
99
+ path
100
+ end
101
+
102
+ def dump_units_to_build_directory
103
+ dir = ::Dir.mktmpdir
104
+ package.dump_units_to_directory(dir)
105
+ dir
106
+ end
107
+
108
+ def create_package_file(build_dir)
109
+ package_path = new_build_path
110
+ infom "Creating package \"#{package_path}\" from \"#{build_dir}\"..."
111
+ Dir.chdir(build_dir) do
112
+ ::Minitar.pack('.', File.open(::File.expand_path(package_path), 'wb'))
113
+ end
114
+ package_path
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'minitar'
5
+
6
+ module Avm
7
+ module Data
8
+ class Package
9
+ class Load
10
+ enable_speaker
11
+
12
+ attr_reader :package, :data_file_path
13
+
14
+ def initialize(package, data_file_path)
15
+ @package = package
16
+ @data_file_path = data_file_path
17
+ end
18
+
19
+ def runnable?
20
+ cannot_run_reason.blank?
21
+ end
22
+
23
+ def cannot_run_reason
24
+ return nil if data_file_exist?
25
+
26
+ "Data file \"#{data_file_path}\" does not exist"
27
+ end
28
+
29
+ def run
30
+ raise "Cannot run: #{cannot_run_reason}" unless runnable?
31
+
32
+ build_dir = extract_packages_to_build_directory
33
+ package.load_units_from_directory(build_dir)
34
+ end
35
+
36
+ def data_file_exist?
37
+ ::File.exist?(data_file_path)
38
+ end
39
+
40
+ def extract_packages_to_build_directory
41
+ dir = ::Dir.mktmpdir
42
+ ::Minitar.unpack(data_file_path, dir)
43
+ dir
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'avm/data/package/dump'
4
+ require 'avm/data/package/load'
5
+
6
+ module Avm
7
+ module Data
8
+ class Package
9
+ attr_reader :units
10
+
11
+ def initialize(options)
12
+ @units = {}
13
+ options = options.to_options_consumer
14
+ units = options.consume(:units)
15
+ options.validate
16
+ units.if_present do |v|
17
+ v.each { |identifier, unit| add_unit(identifier, unit) }
18
+ end
19
+ end
20
+
21
+ def add_unit(identifier, unit)
22
+ @units[identifier.to_sym] = unit
23
+ end
24
+
25
+ def dump(data_path, options = {})
26
+ ::Avm::Data::Package::Dump.new(self, data_path, options)
27
+ end
28
+
29
+ def load(data_path)
30
+ ::Avm::Data::Package::Load.new(self, data_path)
31
+ end
32
+
33
+ def dump_units_to_directory(directory)
34
+ @units.each { |identifier, unit| unit.dump_to_directory(directory, identifier) }
35
+ end
36
+
37
+ def load_units_from_directory(directory)
38
+ @units.each { |identifier, unit| unit.load_from_directory(directory, identifier) }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'active_support/callbacks'
5
+
6
+ module Avm
7
+ module Data
8
+ class Unit
9
+ include ::ActiveSupport::Callbacks
10
+
11
+ define_callbacks :dump, :load
12
+ enable_speaker
13
+
14
+ %w[dump load].each do |action|
15
+ method_name = "#{action}_command"
16
+ class_eval <<~CODE, __FILE__, __LINE__ + 1
17
+ # Should be overrided.
18
+ # @return [EacRubyUtils::Envs::Command]
19
+ def #{method_name}
20
+ fail "\\"#{method_name}\\" is a abstract method. Override in #{singleton_class}."
21
+ end
22
+ CODE
23
+
24
+ # Callbacks
25
+ %w[before after].each do |callback|
26
+ method = "#{callback}_#{action}"
27
+ class_eval <<~CODE, __FILE__, __LINE__ + 1
28
+ def self.#{method}(callback_method = nil, &block)
29
+ if callback_method
30
+ set_callback :#{action}, :#{callback}, callback_method
31
+ else
32
+ set_callback :#{action}, :#{callback}, &block
33
+ end
34
+ self
35
+ end
36
+
37
+ def #{method}(callback_method = nil, &block)
38
+ singleton_class.#{method}(callback_method, &block)
39
+ self
40
+ end
41
+ CODE
42
+ end
43
+ end
44
+
45
+ def extension
46
+ singleton_class.const_get('EXTENSION')
47
+ rescue NameError
48
+ ''
49
+ end
50
+
51
+ def name
52
+ self.class
53
+ end
54
+
55
+ def load_from_directory(directory, identifier)
56
+ load(unit_on_directory_path(directory, identifier))
57
+ end
58
+
59
+ def dump_to_directory(directory, identifier)
60
+ dump(unit_on_directory_path(directory, identifier))
61
+ end
62
+
63
+ def dump(data_path)
64
+ run_callbacks :dump do
65
+ infom "Dumping unit \"#{name}\" to \"#{data_path}\"..."
66
+ do_dump(data_path)
67
+ end
68
+ end
69
+
70
+ def load(data_path)
71
+ run_callbacks :load do
72
+ infom "Loading unit \"#{name}\" from \"#{data_path}\"..."
73
+ do_load(data_path)
74
+ end
75
+ end
76
+
77
+ protected
78
+
79
+ def do_dump(data_path)
80
+ dump_command.execute!(output_file: data_path)
81
+ end
82
+
83
+ def do_load(data_path)
84
+ load_command.execute!(input_file: data_path)
85
+ end
86
+
87
+ private
88
+
89
+ def unit_on_directory_path(directory, identifier)
90
+ ::File.join(directory, "#{identifier}#{extension}")
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'avm/app_src/configuration'
3
+ require 'avm/sources/configuration'
4
4
  require 'avm/result'
5
5
  require 'eac_ruby_utils/fs/temp'
6
6
 
@@ -36,7 +36,7 @@ module Avm
36
36
  end
37
37
 
38
38
  def configuration_uncached
39
- ::Avm::AppSrc::Configuration.find_by_path(@git)
39
+ ::Avm::Sources::Configuration.find_by_path(@git)
40
40
  end
41
41
  end
42
42
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/object/blank'
4
+
5
+ module Avm
6
+ # String with paths like PATH variable.
7
+ # Note: the separator is not system dependent.
8
+ class PathString < String
9
+ SEPARATOR = ':'
10
+
11
+ class << self
12
+ # Shortcut for [Avm::Paths.new(string).paths].
13
+ def paths(string)
14
+ new(string).paths
15
+ end
16
+ end
17
+
18
+ def initialize(string = nil)
19
+ super(string.to_s)
20
+ end
21
+
22
+ # @return [Array] List of paths. Blank paths are rejected.
23
+ def paths
24
+ split(SEPARATOR).reject(&:blank?)
25
+ end
26
+ end
27
+ end
@@ -4,7 +4,7 @@ require 'eac_git'
4
4
  require 'eac_ruby_utils/core_ext'
5
5
 
6
6
  module Avm
7
- module AppSrc
7
+ module Sources
8
8
  class Base
9
9
  enable_simple_cache
10
10
  enable_listable
@@ -16,7 +16,7 @@ module Avm
16
16
 
17
17
  delegate :to_s, to: :path
18
18
 
19
- # @return [Avm::AppSrc::Base]
19
+ # @return [Avm::Sources::Base]
20
20
  def parent
21
21
  options[OPTION_PARENT]
22
22
  end
@@ -28,7 +28,7 @@ module Avm
28
28
  path.relative_path_from(parent.path)
29
29
  end
30
30
 
31
- # @return [Enumerable<Avm::AppSrc::Base>]
31
+ # @return [Enumerable<Avm::Sources::Base>]
32
32
  def subs
33
33
  git_repo.subrepos
34
34
  .map { |subrepo| self.class.new(subrepo.subpath.expand_path(path), parent: self) }
@@ -4,7 +4,7 @@ require 'avm/patches/eac_ruby_gems_utils/gem'
4
4
  require 'i18n'
5
5
 
6
6
  module Avm
7
- module AppSrc
7
+ module Sources
8
8
  class Configuration < ::EacConfig::OldConfigs
9
9
  LOCALE_KEY = :locale
10
10
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Avm
4
- module AppSrc
4
+ module Sources
5
5
  class Configuration < ::EacConfig::OldConfigs
6
6
  RUBOCOP_COMMAND_KEY = 'ruby.rubocop.command'
7
7
  RUBOCOP_GEMFILE_KEY = 'ruby.rubocop.gemfile'
@@ -3,7 +3,7 @@
3
3
  require 'avm/patches/eac_ruby_gems_utils/gem'
4
4
 
5
5
  module Avm
6
- module AppSrc
6
+ module Sources
7
7
  class Configuration < ::EacConfig::OldConfigs
8
8
  BUNDLE_TEST_COMMAND_KEY = 'test.bundle_command'
9
9
  TEST_COMMAND_KEY = 'test.command'
@@ -5,7 +5,7 @@ require 'eac_ruby_utils/core_ext'
5
5
  require 'yaml'
6
6
 
7
7
  module Avm
8
- module AppSrc
8
+ module Sources
9
9
  class Configuration < ::EacConfig::OldConfigs
10
10
  require_sub __FILE__
11
11
 
@@ -3,7 +3,7 @@
3
3
  require 'eac_ruby_utils/core_ext'
4
4
 
5
5
  module Avm
6
- module AppSrc
6
+ module Sources
7
7
  require_sub __FILE__
8
8
  end
9
9
  end
data/lib/avm/sync.rb ADDED
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Avm
6
+ class Sync
7
+ attr_reader :excludes, :includes
8
+
9
+ common_constructor :source_path, :target_path do
10
+ self.source_path = source_path.to_pathname
11
+ self.target_path = target_path.to_pathname
12
+ @excludes = []
13
+ @includes = []
14
+ end
15
+
16
+ def run
17
+ clear_target
18
+ copy
19
+ end
20
+
21
+ def add_exclude(exclude)
22
+ excludes << exclude
23
+
24
+ self
25
+ end
26
+
27
+ def add_excludes(*excludes)
28
+ excludes.each { |exclude| add_exclude(exclude) }
29
+
30
+ self
31
+ end
32
+
33
+ def add_include(include)
34
+ includes << include
35
+
36
+ self
37
+ end
38
+
39
+ def add_includes(*includes)
40
+ includes.each { |include| add_include(include) }
41
+
42
+ self
43
+ end
44
+
45
+ def move_mode(value)
46
+ @move_mode = value
47
+
48
+ self
49
+ end
50
+
51
+ def move_mode?
52
+ @move_mode ? true : false
53
+ end
54
+
55
+ private
56
+
57
+ def clear_target
58
+ target_remove(target_path)
59
+ target_path.children.each { |tchild| target_remove(tchild) }
60
+ end
61
+
62
+ def copy
63
+ source_path.children.each do |schild|
64
+ ::FileUtils.cp_r(schild.to_path, target_path.to_path)
65
+ schild.rmtree if move_mode?
66
+ end
67
+ end
68
+
69
+ def source_to_target_path(source_path)
70
+ source_path.relative_path_from(self.source_path).expand_path(target_path)
71
+ end
72
+
73
+ def target_remove(tpath)
74
+ return if skip_target_path?(tpath)
75
+
76
+ if tpath.directory?
77
+ tpath.children.each { |tchild| target_remove(tchild) }
78
+ tpath.rmdir if tpath.children.empty?
79
+ elsif tpath.file?
80
+ tpath.unlink
81
+ end
82
+ end
83
+
84
+ def skip_target_path?(tpath)
85
+ skip_path?(tpath.relative_path_from(target_path))
86
+ end
87
+
88
+ def skip_path?(relpath)
89
+ relpath = relpath.expand_path('/')
90
+ excludes.any? { |exclude| relpath.fnmatch?(exclude) } &&
91
+ includes.none? { |include| relpath.fnmatch?(include) }
92
+ end
93
+ end
94
+ end
data/lib/avm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Avm
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo H. Bogoni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-25 00:00:00.000000000 Z
11
+ date: 2021-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eac_docker
@@ -161,12 +161,14 @@ extensions: []
161
161
  extra_rdoc_files: []
162
162
  files:
163
163
  - lib/avm.rb
164
- - lib/avm/app_src.rb
165
- - lib/avm/app_src/base.rb
166
- - lib/avm/app_src/configuration.rb
167
- - lib/avm/app_src/configuration/_locale.rb
168
- - lib/avm/app_src/configuration/_rubocop.rb
169
- - lib/avm/app_src/configuration/_tests.rb
164
+ - lib/avm/data/instance.rb
165
+ - lib/avm/data/instance/files_unit.rb
166
+ - lib/avm/data/instance/package.rb
167
+ - lib/avm/data/instance/unit.rb
168
+ - lib/avm/data/package.rb
169
+ - lib/avm/data/package/dump.rb
170
+ - lib/avm/data/package/load.rb
171
+ - lib/avm/data/unit.rb
170
172
  - lib/avm/docker.rb
171
173
  - lib/avm/docker/container.rb
172
174
  - lib/avm/docker/image.rb
@@ -239,7 +241,15 @@ files:
239
241
  - lib/avm/jobs.rb
240
242
  - lib/avm/jobs/base.rb
241
243
  - lib/avm/jobs/variables_source.rb
244
+ - lib/avm/path_string.rb
242
245
  - lib/avm/result.rb
246
+ - lib/avm/sources.rb
247
+ - lib/avm/sources/base.rb
248
+ - lib/avm/sources/configuration.rb
249
+ - lib/avm/sources/configuration/_locale.rb
250
+ - lib/avm/sources/configuration/_rubocop.rb
251
+ - lib/avm/sources/configuration/_tests.rb
252
+ - lib/avm/sync.rb
243
253
  - lib/avm/version.rb
244
254
  - lib/avm/version_number.rb
245
255
  homepage: