eco-helpers 2.5.3 → 2.5.4
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 +4 -4
- data/CHANGELOG.md +17 -2
- data/lib/eco/api/organization/tag_tree.rb +2 -2
- data/lib/eco/api/usecases/graphql/helpers/base/case_env.rb +15 -0
- data/lib/eco/api/usecases/graphql/helpers/base.rb +3 -11
- data/lib/eco/api/usecases/graphql/helpers/location/command.rb +14 -6
- data/lib/eco/api/usecases/graphql/utils/sftp.rb +74 -0
- data/lib/eco/api/usecases/graphql/utils.rb +6 -0
- data/lib/eco/api/usecases/graphql.rb +1 -0
- data/lib/eco/data/files/helpers.rb +3 -3
- data/lib/eco/data/hashes/array_diff.rb +11 -57
- data/lib/eco/data/hashes/diff_meta.rb +52 -0
- data/lib/eco/data/hashes/diff_result.rb +37 -25
- data/lib/eco/data/hashes.rb +1 -0
- data/lib/eco/data/locations/node_diff/accessors.rb +46 -0
- data/lib/eco/data/locations/node_diff/nodes_diff.rb +90 -0
- data/lib/eco/data/locations/node_diff/selectors.rb +20 -0
- data/lib/eco/data/locations/node_diff.rb +55 -0
- data/lib/eco/data/locations/node_level.rb +1 -4
- data/lib/eco/data/locations/node_plain.rb +2 -5
- data/lib/eco/data/locations.rb +1 -0
- data/lib/eco/version.rb +1 -1
- metadata +9 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 444bec4cd18402a38eff718340932ca7d72c9959b865805964b0ec9787d94636
|
4
|
+
data.tar.gz: 97291544f70b525781d81f168ffc86c1d960151e53535a540ac1b7824b9eaf28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02360de987395d801aa1b1fb659dd4b6011c317a21058be33c3283b3a2856c69db519baf6eb85a022f7a2c7c4e826861b108c2cf09aefad3ca57b32d53b45c72
|
7
|
+
data.tar.gz: 402c880d701446c072f6534d4df35b2a104704dc79480e37e5033101df63a8b10baa25257911af1cc84994efe05744b15c608798dbc1637ad268811ca2d7d926
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,23 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [2.5.
|
4
|
+
## [2.5.5] - 2023-07-xx
|
5
|
+
|
6
|
+
### Added
|
7
|
+
### Changed
|
8
|
+
### Fixed
|
9
|
+
|
10
|
+
## [2.5.4] - 2023-07-27
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- SFTP case helpers: `Eco::API::UseCases::GraphQL::Utils::Sftp`
|
14
|
+
- `Eco::Data::Locations::NodeDiff` and `Eco::Data::Locations::NodeDiff::NodeDiffs`
|
15
|
+
- Aim to identify changes in the locations structure
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
- Some internal tidy up in `Eco::API::UseCases::GraphQL`
|
19
|
+
|
20
|
+
## [2.5.3] - 2023-07-19
|
5
21
|
|
6
22
|
### Added
|
7
23
|
- _GraphQL base case_ for **locations structure update**.
|
@@ -52,7 +68,6 @@ All notable changes to this project will be documented in this file.
|
|
52
68
|
- `Eco::API::Session::Config::Workflow#exit_handle`
|
53
69
|
- Allows to define a callback on `SystemExit` (`exit` call).
|
54
70
|
|
55
|
-
### Changed
|
56
71
|
### Fixed
|
57
72
|
- `Eco::API::Session::Config::Workflow` on `SystemExit` preserve original exit `status` value (i.e. `0`, `1`)
|
58
73
|
- It was changing an `exit 1` to be an `exit 0`
|
@@ -180,8 +180,8 @@ module Eco
|
|
180
180
|
|
181
181
|
# Returns a plain list form of hash nodes.
|
182
182
|
# @return [Array[Hash]] where `Hash` is a plain `node`
|
183
|
-
def as_nodes_json
|
184
|
-
all_nodes.map {|nd| nd.as_json(include_children: false)}
|
183
|
+
def as_nodes_json(&block)
|
184
|
+
all_nodes.map {|nd| nd.as_json(include_children: false, &block)}
|
185
185
|
end
|
186
186
|
|
187
187
|
# @return [Boolean] `true` if there are tags in the node, `false` otherwise.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Helpers::Base
|
2
|
+
# Basic stuff you would need in any use case
|
3
|
+
module CaseEnv
|
4
|
+
include Eco::Language::AuxiliarLogger
|
5
|
+
attr_reader :session, :options
|
6
|
+
|
7
|
+
def config
|
8
|
+
session.config
|
9
|
+
end
|
10
|
+
|
11
|
+
def simulate?
|
12
|
+
options.dig(:simulate)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,20 +1,12 @@
|
|
1
1
|
module Eco::API::UseCases::GraphQL::Helpers
|
2
2
|
module Base
|
3
|
-
|
4
|
-
|
3
|
+
require_relative 'base/case_env'
|
4
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
|
5
5
|
|
6
6
|
def graphql
|
7
7
|
@graphql ||= session.api(version: :graphql)
|
8
8
|
end
|
9
9
|
|
10
|
-
def config
|
11
|
-
session.config
|
12
|
-
end
|
13
|
-
|
14
|
-
def simulate?
|
15
|
-
options.dig(:simulate)
|
16
|
-
end
|
17
|
-
|
18
10
|
# Keep a copy of the requests/responses for future reference
|
19
11
|
def backup(data, type:)
|
20
12
|
dry_run = simulate? ? "_dry_run" : ""
|
@@ -24,7 +16,7 @@ module Eco::API::UseCases::GraphQL::Helpers
|
|
24
16
|
end
|
25
17
|
|
26
18
|
def exit_error(msg)
|
27
|
-
|
19
|
+
log(:error) { msg }
|
28
20
|
exit(1)
|
29
21
|
end
|
30
22
|
end
|
@@ -3,17 +3,25 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
|
|
3
3
|
include Eco::Language::AuxiliarLogger
|
4
4
|
include Eco::API::UseCases::GraphQL::Helpers::Location::Base
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
# Whether to stop or continue on command fail
|
9
|
-
FORCE_CONTINUE = false
|
6
|
+
DEFAULT_COMMANDS_PER_PAGE = 45
|
7
|
+
DEFAULT_FORCE_CONTINUE = false
|
10
8
|
|
9
|
+
# Prevents each request from timing out
|
11
10
|
def commands_per_page
|
12
|
-
self.class
|
11
|
+
if self.class.const_defined?(:COMMANDS_PER_PAGE)
|
12
|
+
self.class::COMMANDS_PER_PAGE
|
13
|
+
else
|
14
|
+
DEFAULT_COMMANDS_PER_PAGE
|
15
|
+
end
|
13
16
|
end
|
14
17
|
|
18
|
+
# Whether to stop or continue on command fail
|
15
19
|
def force_continue?
|
16
|
-
self.class
|
20
|
+
if self.class.const_defined?(:FORCE_CONTINUE)
|
21
|
+
self.class::FORCE_CONTINUE
|
22
|
+
else
|
23
|
+
DEFAULT_FORCE_CONTINUE
|
24
|
+
end
|
17
25
|
end
|
18
26
|
|
19
27
|
# With given the commands, it generates the input of the endpoint mutation.
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Eco::API::UseCases::GraphQL::Utils
|
2
|
+
module Sftp
|
3
|
+
include Eco::API::UseCases::GraphQL::Helpers::Base::CaseEnv
|
4
|
+
|
5
|
+
|
6
|
+
def remote_subfolder
|
7
|
+
nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def remote_folder(subfolder = remote_subfolder)
|
11
|
+
"#{sftp_config.remote_folder}/#{subfolder || ''}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def sftp_group_id
|
15
|
+
if self.class.const_defined?(:SFTP_GROUP)
|
16
|
+
self.class.const_get(:TARGET_STRUCTURE_ID)
|
17
|
+
elsif group_id = options.dig(:sftp, :group)
|
18
|
+
group_id
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def upload(local_file, remote_folder: self.remote_folder, gid: sftp_group_id)
|
23
|
+
return false unless local_file && File.exists?(local_file)
|
24
|
+
dest_file = "#{remote_folder}/#{File.basename(local_file)}"
|
25
|
+
res = sftp_session.upload!(local_file, dest_file)
|
26
|
+
attrs = sftp_session.stat!(dest_file)
|
27
|
+
if gid && gid != attrs.gid
|
28
|
+
stat_res = sftp_session.setstat!(dest_file, {permissions: 0660, uid: attrs.uid, gid: gid})
|
29
|
+
end
|
30
|
+
logger.info("Uploaded '#{local_file}' (#{res})")
|
31
|
+
end
|
32
|
+
|
33
|
+
def ensure_remote_empty
|
34
|
+
files = with_remote_files
|
35
|
+
unless files.empty?
|
36
|
+
msg = "There are still files in the remote folder that will be deleted: '#{remote_folder}':\n"
|
37
|
+
msg += " • " + files.map do |file|
|
38
|
+
file.longname
|
39
|
+
end.join("\n • ") + "\n"
|
40
|
+
session.prompt_user("Do you want to proceed to delete? (Y/n):", explanation: msg, default: "Y", timeout: 3) do |response|
|
41
|
+
if response.upcase.start_with?("Y")
|
42
|
+
files.each do |file|
|
43
|
+
remote_full_path = to_remote_path(file.name)
|
44
|
+
res = sftp_session.remove(remote_full_path)
|
45
|
+
logger.info("Deleted remote file: '#{remote_full_path}' (#{res})")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def with_remote_files
|
53
|
+
sftp.files(remote_folder).each do |remote_file|
|
54
|
+
yield(remote_file) if block_given?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_remote_path(file, subfolder: nil)
|
59
|
+
remote_folder(subfolder) + "/" + file
|
60
|
+
end
|
61
|
+
|
62
|
+
def sftp_config
|
63
|
+
session.config.sftp
|
64
|
+
end
|
65
|
+
|
66
|
+
def sftp_session
|
67
|
+
sftp.sftp_session
|
68
|
+
end
|
69
|
+
|
70
|
+
def sftp
|
71
|
+
session.sftp
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -75,11 +75,11 @@ module Eco
|
|
75
75
|
Dir.exist?(path) || Dir.exist?(File.expand_path(path))
|
76
76
|
end
|
77
77
|
|
78
|
-
def timestamp(timestamp_pattern = DEFAULT_TIMESTAMP_PATTERN)
|
79
|
-
|
78
|
+
def timestamp(timestamp_pattern = DEFAULT_TIMESTAMP_PATTERN, date = Time.now)
|
79
|
+
date.strftime(timestamp_pattern)
|
80
80
|
end
|
81
81
|
|
82
|
-
def timestamp_file(filename, timestamp_pattern =
|
82
|
+
def timestamp_file(filename, timestamp_pattern =DEFAULT_TIMESTAMP_PATTERN)
|
83
83
|
file_pattern = Eco::Data::Files::FilePattern.new(filename)
|
84
84
|
file_pattern.resolve(start: timestamp(timestamp_pattern) + '_')
|
85
85
|
end
|
@@ -3,47 +3,16 @@ module Eco
|
|
3
3
|
module Hashes
|
4
4
|
class ArrayDiff
|
5
5
|
extend Eco::Language::Models::ClassHelpers
|
6
|
-
|
7
|
-
|
8
|
-
def key(value = nil)
|
9
|
-
return @key unless value
|
10
|
-
@key = value.to_s
|
11
|
-
end
|
12
|
-
|
13
|
-
def key?
|
14
|
-
!!@key
|
15
|
-
end
|
16
|
-
|
17
|
-
def compare(*attrs)
|
18
|
-
compared_attrs.push(*attrs.map(&:to_s)).uniq!
|
19
|
-
end
|
20
|
-
|
21
|
-
def case_sensitive(value = nil)
|
22
|
-
@case_sensitive = false unless instance_variable_defined?(:@case_sensitive)
|
23
|
-
return @case_sensitive unless value
|
24
|
-
@case_sensitive = !!value
|
25
|
-
end
|
26
|
-
|
27
|
-
def case_sensitive?
|
28
|
-
!!@case_sensitive
|
29
|
-
end
|
30
|
-
|
31
|
-
def compared_attrs
|
32
|
-
@compared_attrs ||= []
|
33
|
-
@compared_attrs
|
34
|
-
end
|
35
|
-
end
|
6
|
+
# We can change the `DiffResult` class (items)
|
7
|
+
class_resolver :diff_result_class, "Eco::Data::Hash::DiffResult"
|
36
8
|
|
37
9
|
include Eco::Language::AuxiliarLogger
|
38
10
|
|
39
11
|
attr_reader :source1, :source2
|
40
12
|
attr_reader :src_h1, :src_h2
|
41
13
|
|
42
|
-
|
43
|
-
|
44
|
-
def initialize(source1, source2, logger: nil, **kargs)
|
14
|
+
def initialize(source1, source2, logger: nil)
|
45
15
|
@logger = logger if logger
|
46
|
-
@options = kargs
|
47
16
|
@source1 = source1
|
48
17
|
@source2 = source2
|
49
18
|
@src_h1 = by_key(source1)
|
@@ -67,14 +36,11 @@ module Eco
|
|
67
36
|
!diffs.empty?
|
68
37
|
end
|
69
38
|
|
39
|
+
# All the items that contain the diff of a node.
|
40
|
+
# @return [Array<Eco::Data::Hash::DiffResult>]
|
70
41
|
def source_results
|
71
42
|
@source_results ||= paired_sources.each_with_object([]) do |(src1, src2), res|
|
72
|
-
|
73
|
-
key: key,
|
74
|
-
compare: compared_attrs,
|
75
|
-
case_sensitive: case_sensitive?
|
76
|
-
}
|
77
|
-
res << diff_result_class.new(src1, src2, **args)
|
43
|
+
res << diff_result_class.new(src1, src2)
|
78
44
|
end
|
79
45
|
end
|
80
46
|
|
@@ -91,35 +57,23 @@ module Eco
|
|
91
57
|
all_keys.map {|key| [src_h1[key], src_h2[key]]}
|
92
58
|
end
|
93
59
|
|
60
|
+
# @return [String] the `key` attribute of `diff_result_class`
|
94
61
|
def key
|
95
|
-
|
96
|
-
|
97
|
-
end.tap do |k|
|
98
|
-
raise "missing main key attr to pair records. Given: #{k}" unless k.is_a?(String)
|
62
|
+
diff_result_class.key.tap do |k|
|
63
|
+
raise "#{diff_result_class}: missing main key attr to pair records. Given: #{k}" unless k.is_a?(String)
|
99
64
|
end
|
100
65
|
end
|
101
66
|
|
102
67
|
def case_sensitive?
|
103
|
-
|
68
|
+
diff_result_class.case_sensitive?
|
104
69
|
end
|
105
70
|
|
106
71
|
def compared_attrs
|
107
|
-
|
108
|
-
self.class.compared_attrs
|
109
|
-
end.yield_self do |attrs|
|
110
|
-
raise "compared_attrs should be an array" unless attrs.is_a?(Array)
|
111
|
-
attrs.map(&:to_s)
|
112
|
-
end
|
72
|
+
diff_result_class.compared_attrs.map(&:to_s)
|
113
73
|
end
|
114
74
|
|
115
75
|
private
|
116
76
|
|
117
|
-
def options_or(opt)
|
118
|
-
opt = opt.to_sym
|
119
|
-
return @options[opt] if @options.key?(opt)
|
120
|
-
yield
|
121
|
-
end
|
122
|
-
|
123
77
|
def symbolize_keys(hash)
|
124
78
|
hash.each_with_object({}) do |(k, v), h|
|
125
79
|
h[k.to_sym] = v
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Eco
|
2
|
+
module Data
|
3
|
+
module Hashes
|
4
|
+
module DiffMeta
|
5
|
+
class << self
|
6
|
+
def included(base)
|
7
|
+
super(base)
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# @param value [String, NilClass]
|
14
|
+
# @return [String] the attribute that is key of the node diff elements.
|
15
|
+
def key(value = nil)
|
16
|
+
return @key unless value
|
17
|
+
@key = value.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Boolean] is there a `key` attribute defined?
|
21
|
+
def key?
|
22
|
+
!!@key
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param attrs [Array<Symbol>, Array<String>]
|
26
|
+
# @return [Array<String>] the comparable attributes
|
27
|
+
def compare(*attrs)
|
28
|
+
compared_attrs.push(*attrs.map(&:to_s)).uniq!
|
29
|
+
compared_attrs
|
30
|
+
end
|
31
|
+
|
32
|
+
# Whether or not the diff calc of a node should be done case sensitive or insensitive.
|
33
|
+
def case_sensitive(value = nil)
|
34
|
+
@case_sensitive = false unless instance_variable_defined?(:@case_sensitive)
|
35
|
+
return @case_sensitive unless value
|
36
|
+
@case_sensitive = !!value
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Boolean] are comparisons of values done case sensitive?
|
40
|
+
def case_sensitive?
|
41
|
+
!!@case_sensitive
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Array<String>] the comparable attributes
|
45
|
+
def compared_attrs
|
46
|
+
@compared_attrs ||= []
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -2,19 +2,32 @@ module Eco
|
|
2
2
|
module Data
|
3
3
|
module Hashes
|
4
4
|
class DiffResult
|
5
|
-
|
5
|
+
extend Eco::Language::Models::ClassHelpers
|
6
|
+
include Eco::Data::Hashes::DiffMeta
|
7
|
+
|
8
|
+
inheritable_class_vars :key, :compared_attrs, :case_sensitive
|
9
|
+
|
6
10
|
attr_reader :src1, :src2
|
7
11
|
|
8
|
-
|
9
|
-
# - `:all` compares the matching attrs between both hashes only
|
10
|
-
def initialize(src1, src2, key:, compare: :all, case_sensitive: false)
|
11
|
-
@key = key
|
12
|
-
@compare = compare
|
13
|
-
@case_sensitive = case_sensitive
|
12
|
+
def initialize(src1, src2)
|
14
13
|
@src1 = src1
|
15
14
|
@src2 = src2
|
16
15
|
end
|
17
16
|
|
17
|
+
def key
|
18
|
+
self.class.key
|
19
|
+
end
|
20
|
+
|
21
|
+
def case_sensitive?
|
22
|
+
self.class.case_sensitive?
|
23
|
+
end
|
24
|
+
|
25
|
+
def dup(src1: nil, src2: nil)
|
26
|
+
src1 ||= self.src1
|
27
|
+
src2 ||= self.src2
|
28
|
+
self.class.new(src1.dup, src2.dup)
|
29
|
+
end
|
30
|
+
|
18
31
|
def new?
|
19
32
|
!src1 && !!src2
|
20
33
|
end
|
@@ -27,35 +40,39 @@ module Eco
|
|
27
40
|
!new? && !del? && diff?
|
28
41
|
end
|
29
42
|
|
43
|
+
# @note `diff_attrs` may not include the `key` attribute
|
44
|
+
# This is always included via `new?` (new key value) and `del?` (missing key value)
|
45
|
+
# @return [Boolean] was there any change?
|
30
46
|
def diff?
|
31
47
|
new? || del? || !diff_attrs.empty?
|
32
48
|
end
|
33
49
|
|
34
|
-
# Is the key attr value changing?
|
50
|
+
# Is the `key` attr value changing?
|
35
51
|
def key?
|
36
52
|
!(new? || del?) && diff_attr?(key)
|
37
53
|
end
|
38
54
|
|
55
|
+
# Is `attr` part of the attributes that change?
|
39
56
|
def diff_attr?(attr)
|
40
57
|
return true if new?
|
41
58
|
return true if del?
|
42
59
|
diff_attrs.include?(attr.to_s)
|
43
60
|
end
|
44
61
|
|
62
|
+
# @return [Value] the current value of `attr` (in `src2`)
|
45
63
|
def attr(attr)
|
46
64
|
return nil unless src2
|
47
65
|
src2[attr.to_s]
|
48
66
|
end
|
49
67
|
|
68
|
+
# @return [Value] the previous value of `attr` (in `src1`)
|
50
69
|
def attr_prev(attr)
|
51
70
|
return nil unless src1
|
52
71
|
src1[attr.to_s]
|
53
72
|
end
|
54
73
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
|
74
|
+
# @note the `key` attribute will always be added (even if there's no change)
|
75
|
+
# @return [Hash] hash with the differences as per `src2`
|
59
76
|
def diff_hash
|
60
77
|
target_attrs = [key] | compared_attrs
|
61
78
|
return src2.slice(*target_attrs) if new?
|
@@ -63,12 +80,14 @@ module Eco
|
|
63
80
|
src2.slice(key, *diff_attrs)
|
64
81
|
end
|
65
82
|
|
83
|
+
# @return [Array<Symbol>] hash with the differences as per `src2`
|
66
84
|
def diff_attrs
|
67
85
|
@diff_attrs ||= comparable_attrs.each_with_object([]) do |attr, out|
|
68
86
|
out << attr unless eq?(src1[attr], src2[attr])
|
69
87
|
end
|
70
88
|
end
|
71
89
|
|
90
|
+
# @return [Boolean] whether `val1` is equal to `val2`
|
72
91
|
def eq?(val1, val2)
|
73
92
|
return true if val1 == val2
|
74
93
|
return false if case_sensitive?
|
@@ -76,25 +95,18 @@ module Eco
|
|
76
95
|
val1.upcase == val2.upcase
|
77
96
|
end
|
78
97
|
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
98
|
+
# @note when is `new?` or to be deleted (`del?`), it returns empty array.
|
99
|
+
# @return [Array<String>] the set of attributes that are comparable in this instance.
|
83
100
|
def comparable_attrs
|
84
101
|
return [] if new? || del?
|
85
102
|
compared_attrs
|
86
103
|
end
|
87
104
|
|
105
|
+
# @return [Array<String>] the set of attributes that are comparable in this class.
|
88
106
|
def compared_attrs
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
src1.keys & src2.keys
|
93
|
-
elsif @compare.is_a?(Array)
|
94
|
-
@compare.map(&:to_s)
|
95
|
-
else
|
96
|
-
raise "Expecting 'compare' to be sym (:all) or Array<String>. Given: #{@compare.class}"
|
97
|
-
end
|
107
|
+
comp_attrs = self.class.compared_attrs.map(&:to_s).uniq
|
108
|
+
return comp_attrs unless comp_attrs.empty?
|
109
|
+
(src1&.keys || []) & (src2&.keys || [])
|
98
110
|
end
|
99
111
|
end
|
100
112
|
end
|
data/lib/eco/data/hashes.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
class Eco::Data::Locations::NodeDiff
|
2
|
+
module Accessors
|
3
|
+
class << self
|
4
|
+
def included(base)
|
5
|
+
super(base)
|
6
|
+
base.extend Eco::Language::Models::ClassHelpers
|
7
|
+
base.extend ClassMethods
|
8
|
+
base.inheritable_class_vars :exposed_attrs
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# Creates the defined accessor attributes against `NodeDiff`
|
14
|
+
# It also creates a method with question mark that evaluates true if **any** the attr changed.
|
15
|
+
# @note the defined attributes are expected to be the keys within
|
16
|
+
# the source Hashes that are being compared.
|
17
|
+
# @note accessing `src1` (prev) attributes, will have it's method as `prev_[attrName]`
|
18
|
+
def attr_expose(*attrs)
|
19
|
+
attrs.each do |attr|
|
20
|
+
meth = attr.to_sym
|
21
|
+
methp = "prev_#{meth}".to_sym
|
22
|
+
methq = "diff_#{meth}?".to_sym
|
23
|
+
|
24
|
+
define_method meth do
|
25
|
+
attr(meth)
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method methp do
|
29
|
+
attr_prev(meth)
|
30
|
+
end
|
31
|
+
|
32
|
+
exposed_attrs |= [meth]
|
33
|
+
|
34
|
+
define_method methq do
|
35
|
+
diff_attr?(meth)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Keeps track on what attributes have been exposed.
|
41
|
+
def exposed_attrs
|
42
|
+
@exposed_attrs ||= []
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Eco::Data::Locations::NodeDiff
|
2
|
+
# Adjusts ArrayDiff for Nodes diffs in a location structure
|
3
|
+
class NodesDiff < Eco::Data::Hashes::ArrayDiff
|
4
|
+
extend Eco::Data::Locations::NodeDiff::Selectors
|
5
|
+
|
6
|
+
SELECTORS = %i[id name id_name insert unarchive update move archive]
|
7
|
+
selector *SELECTORS
|
8
|
+
|
9
|
+
class_resolver :diff_result_class, Eco::Data::Locations::NodeDiff
|
10
|
+
attr_reader :original_tree
|
11
|
+
|
12
|
+
def initialize(*args, original_tree:, **kargs, &block)
|
13
|
+
super(*args, **kargs, &block)
|
14
|
+
@original_tree = original_tree
|
15
|
+
end
|
16
|
+
|
17
|
+
def diffs
|
18
|
+
@diffs ||= super.select do |res|
|
19
|
+
res.unarchive? || res.id_name? || res.insert? || res.move? || res.archive?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def diffs_details
|
24
|
+
section = '#' * 10
|
25
|
+
msg = ''
|
26
|
+
if insert?
|
27
|
+
msg << " #{section} I N S E R T S #{section}\n"
|
28
|
+
msg << insert.map {|d| d.diff_hash.pretty_inspect}.join('')
|
29
|
+
end
|
30
|
+
|
31
|
+
if update?
|
32
|
+
msg << "\n #{section} U P D A T E S #{section}\n"
|
33
|
+
update.each do |d|
|
34
|
+
flags = ''
|
35
|
+
#flags << 'i' if d.id?
|
36
|
+
flags << 'n' if d.diff_name?
|
37
|
+
flags << 'm' if d.move?
|
38
|
+
flags << 'u' if d.unarchive?
|
39
|
+
msg << "<< #{flags} >> "
|
40
|
+
msg << d.diff_hash.pretty_inspect
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if archive?
|
45
|
+
msg << "\n #{section} A R C H I V E S #{section}\n"
|
46
|
+
msg << archive.map {|d| d.diff_hash.pretty_inspect}.join('')
|
47
|
+
end
|
48
|
+
|
49
|
+
msg
|
50
|
+
end
|
51
|
+
|
52
|
+
def diffs_summary
|
53
|
+
return "There were no differences identified" if diffs.empty?
|
54
|
+
msg = "Identified #{diffs.count} differences:\n"
|
55
|
+
msg << when_present(insert, '') do |count|
|
56
|
+
" • #{count} nodes to insert\n"
|
57
|
+
end
|
58
|
+
msg << when_present(update, '') do |count|
|
59
|
+
" • #{count} nodes to update\n"
|
60
|
+
end
|
61
|
+
# msg << when_present(id, '') do |count|
|
62
|
+
# " • #{count} nodes to change id\n"
|
63
|
+
# end
|
64
|
+
msg << when_present(name, '') do |count|
|
65
|
+
" • #{count} nodes to change name\n"
|
66
|
+
end
|
67
|
+
msg << when_present(move, '') do |count|
|
68
|
+
" • #{count} nodes to move\n"
|
69
|
+
end
|
70
|
+
msg << when_present(unarchive, '') do |count|
|
71
|
+
" • #{count} nodes to unarchive\n"
|
72
|
+
end
|
73
|
+
msg << when_present(archive, '') do |count|
|
74
|
+
" • #{count} nodes to archive\n"
|
75
|
+
end
|
76
|
+
msg
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def when_present(list, default = nil)
|
82
|
+
count = list.count
|
83
|
+
if count > 0
|
84
|
+
yield(count)
|
85
|
+
else
|
86
|
+
default
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Eco::Data::Locations::NodeDiff
|
2
|
+
module Selectors
|
3
|
+
# Creates selector methods on `diffs` (nodes that changed)
|
4
|
+
# It also creates a method with question mark that evaluates true if **any** diff matches.
|
5
|
+
# @note the selector method name with a question mark should exist in the `diff_result_class`
|
6
|
+
def selector(*attrs)
|
7
|
+
attrs.each do |attr|
|
8
|
+
meth = attr.to_sym
|
9
|
+
methq = "#{meth}?".to_sym
|
10
|
+
define_method meth do
|
11
|
+
diffs.select(&methq)
|
12
|
+
end
|
13
|
+
|
14
|
+
define_method methq do
|
15
|
+
diffs.any(&methq)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Eco::Data::Locations
|
2
|
+
# Differences between node before and after
|
3
|
+
# @note this works with `Hash` object where basic keys are:
|
4
|
+
# - `nodeId`
|
5
|
+
# - `name`
|
6
|
+
# - `parentId`
|
7
|
+
# - `archived`
|
8
|
+
# @note other properties can be part of the `Hash` although
|
9
|
+
# they may not influence the results.
|
10
|
+
class NodeDiff < Eco::Data::Hashes::DiffResult
|
11
|
+
require_relative 'node_diff/accessors'
|
12
|
+
require_relative 'node_diff/selectors'
|
13
|
+
require_relative 'node_diff/nodes_diff'
|
14
|
+
|
15
|
+
include Eco::Data::Locations::NodeDiff::Accessors
|
16
|
+
|
17
|
+
key :nodeId
|
18
|
+
compare :parentId, :name, :archived
|
19
|
+
case_sensitive false
|
20
|
+
|
21
|
+
attr_expose :nodeId, :name, :parentId, :archived
|
22
|
+
|
23
|
+
alias_method :insert?, :new?
|
24
|
+
|
25
|
+
alias_method :diff_name_src?, :diff_name?
|
26
|
+
# Has the property `name` changed?
|
27
|
+
def diff_name?
|
28
|
+
diff_name_src? && update?
|
29
|
+
end
|
30
|
+
alias_method :name?, :diff_name?
|
31
|
+
alias_method :id? , :diff_name? # currently a change of name is a change of id (tag)
|
32
|
+
#alias_method :id? , :key?
|
33
|
+
#alias_method :nodeId? , :id?
|
34
|
+
|
35
|
+
# Has any of `id` or `name` properties changed?
|
36
|
+
def id_name?
|
37
|
+
id? || diff_name?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Has the parent id changed?
|
41
|
+
def move?
|
42
|
+
update? && diff_parentId?
|
43
|
+
end
|
44
|
+
|
45
|
+
# Has the `archived` property changed and it was `true`?
|
46
|
+
def unarchive?
|
47
|
+
!archived && update? && diff_archived?
|
48
|
+
end
|
49
|
+
|
50
|
+
# Has the `archived` property changed and it was `false`?
|
51
|
+
def archive?
|
52
|
+
!prev_archived && (del? || archived)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -17,6 +17,8 @@ module Eco::Data::Locations
|
|
17
17
|
def id
|
18
18
|
clean_id(super)
|
19
19
|
end
|
20
|
+
# backwards compatibility
|
21
|
+
alias_method :tag, :id
|
20
22
|
|
21
23
|
def name
|
22
24
|
super || self.id
|
@@ -25,10 +27,5 @@ module Eco::Data::Locations
|
|
25
27
|
def parentId
|
26
28
|
self.parent_id
|
27
29
|
end
|
28
|
-
|
29
|
-
# backwards compatibility
|
30
|
-
def tag
|
31
|
-
id
|
32
|
-
end
|
33
30
|
end
|
34
31
|
end
|
data/lib/eco/data/locations.rb
CHANGED
data/lib/eco/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eco-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.5.
|
4
|
+
version: 2.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Segura
|
@@ -592,6 +592,7 @@ files:
|
|
592
592
|
- lib/eco/api/usecases/graphql/base.rb
|
593
593
|
- lib/eco/api/usecases/graphql/helpers.rb
|
594
594
|
- lib/eco/api/usecases/graphql/helpers/base.rb
|
595
|
+
- lib/eco/api/usecases/graphql/helpers/base/case_env.rb
|
595
596
|
- lib/eco/api/usecases/graphql/helpers/location.rb
|
596
597
|
- lib/eco/api/usecases/graphql/helpers/location/base.rb
|
597
598
|
- lib/eco/api/usecases/graphql/helpers/location/command.rb
|
@@ -603,6 +604,8 @@ files:
|
|
603
604
|
- lib/eco/api/usecases/graphql/samples/location/command/dsl.rb
|
604
605
|
- lib/eco/api/usecases/graphql/samples/location/command/results.rb
|
605
606
|
- lib/eco/api/usecases/graphql/samples/location/dsl.rb
|
607
|
+
- lib/eco/api/usecases/graphql/utils.rb
|
608
|
+
- lib/eco/api/usecases/graphql/utils/sftp.rb
|
606
609
|
- lib/eco/api/usecases/ooze_cases.rb
|
607
610
|
- lib/eco/api/usecases/ooze_cases/export_register_case.rb
|
608
611
|
- lib/eco/api/usecases/ooze_samples.rb
|
@@ -670,6 +673,7 @@ files:
|
|
670
673
|
- lib/eco/data/fuzzy_match/string_helpers.rb
|
671
674
|
- lib/eco/data/hashes.rb
|
672
675
|
- lib/eco/data/hashes/array_diff.rb
|
676
|
+
- lib/eco/data/hashes/diff_meta.rb
|
673
677
|
- lib/eco/data/hashes/diff_result.rb
|
674
678
|
- lib/eco/data/locations.rb
|
675
679
|
- lib/eco/data/locations/convert.rb
|
@@ -681,6 +685,10 @@ files:
|
|
681
685
|
- lib/eco/data/locations/node_base/serial.rb
|
682
686
|
- lib/eco/data/locations/node_base/tag_validations.rb
|
683
687
|
- lib/eco/data/locations/node_base/treeify.rb
|
688
|
+
- lib/eco/data/locations/node_diff.rb
|
689
|
+
- lib/eco/data/locations/node_diff/accessors.rb
|
690
|
+
- lib/eco/data/locations/node_diff/nodes_diff.rb
|
691
|
+
- lib/eco/data/locations/node_diff/selectors.rb
|
684
692
|
- lib/eco/data/locations/node_level.rb
|
685
693
|
- lib/eco/data/locations/node_level/builder.rb
|
686
694
|
- lib/eco/data/locations/node_level/cleaner.rb
|