eco-helpers 3.0.4 → 3.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +55 -4
- data/eco-helpers.gemspec +1 -1
- data/lib/eco/api/common/class_helpers.rb +24 -23
- data/lib/eco/api/common/class_meta_basics.rb +0 -2
- data/lib/eco/api/common/loaders/use_case.rb +1 -0
- data/lib/eco/api/common/people/entry_factory.rb +6 -4
- data/lib/eco/api/common/people/person_entry.rb +4 -6
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +25 -12
- data/lib/eco/api/common/people/person_parser.rb +8 -0
- data/lib/eco/api/common/session/base_session.rb +1 -1
- data/lib/eco/api/common/session/environment.rb +7 -0
- data/lib/eco/api/common/session/file_manager.rb +15 -8
- data/lib/eco/api/common/session/logger/cache.rb +14 -10
- data/lib/eco/api/common/session/logger/log.rb +8 -7
- data/lib/eco/api/common/session/mailer.rb +22 -13
- data/lib/eco/api/common/session/s3_uploader.rb +29 -20
- data/lib/eco/api/microcases/people_search.rb +1 -1
- data/lib/eco/api/organization/login_providers.rb +11 -4
- data/lib/eco/api/organization/node_classifications.rb +3 -0
- data/lib/eco/api/organization/presets_factory.rb +37 -31
- data/lib/eco/api/organization/tag_tree.rb +14 -5
- data/lib/eco/api/policies/default_policies/99_user_access_policy.rb +28 -18
- data/lib/eco/api/session/batch/errors.rb +38 -20
- data/lib/eco/api/session/batch/job.rb +252 -135
- data/lib/eco/api/session/batch/status.rb +55 -36
- data/lib/eco/api/session/batch.rb +2 -2
- data/lib/eco/api/session/config/base_config.rb +12 -11
- data/lib/eco/api/session/config/tagtree.rb +10 -14
- data/lib/eco/api/session/config/workflow.rb +15 -3
- data/lib/eco/api/session/config.rb +19 -26
- data/lib/eco/api/session.rb +13 -4
- data/lib/eco/api/usecases/cli.rb +4 -0
- data/lib/eco/api/usecases/default/locations/cli/codes_to_tags_cli.rb +18 -0
- data/lib/eco/api/usecases/default/locations/cli/csv_to_tree_cli.rb +12 -0
- data/lib/eco/api/usecases/default/locations/cli/tagtree_paths_cli.rb +12 -0
- data/lib/eco/api/usecases/default/locations/codes_to_tags_case.rb +32 -13
- data/lib/eco/api/usecases/default/locations/csv_to_tree_case.rb +15 -5
- data/lib/eco/api/usecases/default/locations/tagtree_extract_case.rb +6 -0
- data/lib/eco/api/usecases/default/locations/tagtree_paths_case.rb +51 -0
- data/lib/eco/api/usecases/default/locations.rb +1 -1
- data/lib/eco/api/usecases/default/people/amend/cli/reinvite_sync_cli.rb +8 -0
- data/lib/eco/api/usecases/default/people/amend/cli/reinvite_trans_cli.rb +11 -0
- data/lib/eco/api/usecases/default/people/amend/cli/restore_db_cli.rb +26 -0
- data/lib/eco/api/usecases/default/people/amend/reinvite_sync_case.rb +2 -0
- data/lib/eco/api/usecases/default/people/amend/reinvite_trans_case.rb +2 -0
- data/lib/eco/api/usecases/default/people/amend/restore_db_case.rb +3 -0
- data/lib/eco/api/usecases/default/people/treat/analyse_people_case.rb +15 -5
- data/lib/eco/api/usecases/default/people/treat/cli/analyse_people_cli.rb +66 -0
- data/lib/eco/api/usecases/default/people/treat/cli/org_data_convert_cli.rb +35 -0
- data/lib/eco/api/usecases/default/people/treat/cli/supers_cyclic_identify_cli.rb +15 -0
- data/lib/eco/api/usecases/default/people/treat/cli/supers_hierachy_cli.rb +15 -0
- data/lib/eco/api/usecases/default/people/treat/org_data_convert_case.rb +11 -5
- data/lib/eco/api/usecases/default/people/treat/supers_cyclic_identify_case.rb +28 -7
- data/lib/eco/api/usecases/default/people/treat/supers_hierarchy_case.rb +32 -9
- data/lib/eco/api/usecases/default/people/utils/set_default_tag_case.rb +2 -1
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +2 -2
- data/lib/eco/api/usecases/graphql/helpers/base/case_env.rb +1 -0
- data/lib/eco/api/usecases/graphql/helpers/base/error_handling.rb +52 -0
- data/lib/eco/api/usecases/graphql/helpers/base.rb +1 -0
- data/lib/eco/api/usecases/graphql/helpers/location/base/classifications_parser.rb +5 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/commandable.rb +2 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable.rb +2 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/result.rb +2 -1
- data/lib/eco/api/usecases/graphql/helpers/location/command/results.rb +3 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command.rb +1 -0
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap.rb +3 -0
- data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +19 -18
- data/lib/eco/api/usecases/graphql/samples/location/command/results.rb +1 -7
- data/lib/eco/api/usecases/graphql/samples/location/command/service/tree_update.rb +11 -6
- data/lib/eco/api/usecases/graphql/samples/location/command/track_changed_ids.rb +3 -8
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/classifications.rb +2 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible.rb +5 -2
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff.rb +10 -4
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/parser.rb +6 -2
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter.rb +2 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list.rb +5 -3
- data/lib/eco/api/usecases/ooze_cases/export_register_case.rb +1 -0
- data/lib/eco/api/usecases/ooze_samples/helpers_migration/copying.rb +66 -29
- data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +25 -3
- data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +10 -0
- data/lib/eco/api/usecases/use_case.rb +3 -1
- data/lib/eco/cli/config/use_cases.rb +4 -0
- data/lib/eco/cli/scripting/args_helpers.rb +3 -2
- data/lib/eco/cli/scripting/argument.rb +2 -2
- data/lib/eco/cli_default/input.rb +49 -45
- data/lib/eco/cli_default/input_filters.rb +32 -17
- data/lib/eco/cli_default/options.rb +8 -4
- data/lib/eco/cli_default/people.rb +1 -1
- data/lib/eco/cli_default/people_filters.rb +32 -24
- data/lib/eco/cli_default/usecases.rb +8 -121
- data/lib/eco/cli_default/workflow.rb +6 -4
- data/lib/eco/csv/split.rb +2 -0
- data/lib/eco/csv/table.rb +13 -0
- data/lib/eco/data/files/encoding.rb +15 -8
- data/lib/eco/data/files/helpers.rb +6 -2
- data/lib/eco/data/hashes/diff_result.rb +5 -0
- data/lib/eco/data/locations/node_diff/nodes_diff.rb +13 -0
- data/lib/eco/data/locations/node_diff.rb +4 -0
- data/lib/eco/data/locations/node_level.rb +6 -0
- data/lib/eco/language/auxiliar_logger.rb +2 -0
- data/lib/eco/version.rb +1 -1
- data/lib/eco-helpers.rb +1 -1
- metadata +16 -6
- data/lib/eco/api/usecases/default/locations/create_tag_paths_case.rb +0 -25
- data/lib/eco/api/usecases/default/people/amend/reinvite_trans_cli.rb +0 -4
@@ -1,55 +1,5 @@
|
|
1
|
-
ASSETS.cli.config do |cnf|
|
2
|
-
cnf.usecases do |cases|
|
3
|
-
|
4
|
-
desc = "Draws the Supervisors hiearchy in a file"
|
5
|
-
cases.add("-supers-hierarchy", :export, desc, case_name: "supers-hierarchy") do |people, session, options|
|
6
|
-
options.deep_merge!(output: {file: "supers_hierarchy.txt"}) unless options.dig(:output, :file)
|
7
|
-
end.add_option("-to", "Specify the output file") do |options|
|
8
|
-
file = SCR.get_file("-to", required: true, should_exist: false)
|
9
|
-
options.deep_merge!(output: {file: file})
|
10
|
-
end
|
11
|
-
|
12
|
-
desc = "Draws the Cyclic Supervisors when identified"
|
13
|
-
cases.add("-identify-cyclic-supers", :export, desc, case_name: "identify-cyclic-supers") do |people, session, options|
|
14
|
-
options.deep_merge!(output: {file: "cyclic_supers.txt"}) unless options.dig(:output, :file)
|
15
|
-
end.add_option("-to", "Specify the output file") do |options|
|
16
|
-
file = SCR.get_file("-to", required: true, should_exist: false)
|
17
|
-
options.deep_merge!(output: {file: file})
|
18
|
-
end
|
19
|
-
|
20
|
-
desc = "Provides a set of tools to analyse a set of people (i.e. detect duplicates)"
|
21
|
-
cases.add("-analyse-people", :export, desc, case_name: "analyse-people") do |people, session, options|
|
22
|
-
options.deep_merge!(output: {file: "people_analysis.txt"}) unless options.dig(:output, :file)
|
23
|
-
#unless options.dig(:usecase, :analyse_people, :use_field)
|
24
|
-
# options.deep_merge!(usecase: {analyse_people: {use_field: :name}})
|
25
|
-
#end
|
26
|
-
end.add_option("-to", "Specify the output file.") do |options|
|
27
|
-
file = SCR.get_file("-to", required: true, should_exist: false)
|
28
|
-
options.deep_merge!(output: {file: file})
|
29
|
-
end.add_option("-identify-duplicates", "Generates a list of people with possible duplicates.") do |options|
|
30
|
-
options.deep_merge!(usecase: {analyse_people: {identify_duplicates: true}})
|
31
|
-
end.add_option("-use-field", "Works with -identify-duplicates. Sets field to be used in the comparison.") do |options|
|
32
|
-
expression = SCR.get_arg("-use-field", with_param: true)
|
33
|
-
options.deep_merge!(usecase: {analyse_people: {use_field: expression}})
|
34
|
-
end.add_option("-facet-field", "Works with -identify-duplicates. Adds an additional layer of comparison.") do |options|
|
35
|
-
expression = SCR.get_arg("-facet-field", with_param: true)
|
36
|
-
options.deep_merge!(usecase: {analyse_people: {facet_field: expression}})
|
37
|
-
end.add_option("-only-screening", "Works with -identify-duplicates. Skips the rearrangement stage.") do |options|
|
38
|
-
options.deep_merge!(usecase: {analyse_people: {only_screening: true}})
|
39
|
-
end.add_option("-ignore-matching-words", "Works with -identify-duplicates. Re-adjust scores ignoring matching words.") do |options|
|
40
|
-
options.deep_merge!(usecase: {analyse_people: {ignore_matching_words: true}})
|
41
|
-
end.add_option("-unique-words", "Works with -identify-duplicates. Re-adjust the comparing strings to do not have repeated words.") do |options|
|
42
|
-
options.deep_merge!(usecase: {analyse_people: {unique_words: true}})
|
43
|
-
end.add_option("-identify-unnamed", "Identifies all people with no names.") do |options|
|
44
|
-
options.deep_merge!(usecase: {analyse_people: {identify_unnamed: true}})
|
45
|
-
end.add_option("-backup-people-results", "Generates a json file with all the people involved in the final results of the analysis.") do |options|
|
46
|
-
file = SCR.get_file("-backup-people-results", required: true, should_exist: false)
|
47
|
-
options.deep_merge!(usecase: {analyse_people: {backup_people: File.expand_path(file)}})
|
48
|
-
end.add_option("-to-csv", "Genarates a CSV file with all people of the final results.") do |options|
|
49
|
-
file = SCR.get_file("-to-csv", required: true, should_exist: false) || "Results.csv"
|
50
|
-
options.deep_merge!(usecase: {analyse_people: {csv_file: File.expand_path(file)}})
|
51
|
-
end
|
52
|
-
|
1
|
+
ASSETS.cli.config do |cnf| # rubocop:disable Metrics/BlockLength
|
2
|
+
cnf.usecases do |cases| # rubocop:disable Metrics/BlockLength
|
53
3
|
desc = "It exports to a CSV the (filtered) people"
|
54
4
|
cases.add("-people-to-csv", :export, desc) do |people, session, options|
|
55
5
|
file = SCR.get_file("-people-to-csv", required: true, should_exist: false)
|
@@ -69,25 +19,6 @@ ASSETS.cli.config do |cnf|
|
|
69
19
|
options.deep_merge!(export: {options: {split_schemas: true}})
|
70
20
|
end
|
71
21
|
|
72
|
-
desc = "Adds a column 'ecoPortalTag' to the input CSV with the tags that the location codes map to"
|
73
|
-
cases.add("-codes-to-tags-from", :other, desc, case_name: "codes-to-tags-from")
|
74
|
-
.add_option("-codes-to-tags-from", "Specify the input 'csv' file") do |options|
|
75
|
-
file = SCR.get_file("-codes-to-tags-from", required: true, should_exist: true)
|
76
|
-
options.deep_merge!(other: {file: {name: file, format: :csv}})
|
77
|
-
end.add_option("-column", "Specify the input column header with the codes") do |options|
|
78
|
-
col_codes = SCR.get_arg("-column", with_param: true)
|
79
|
-
options.deep_merge!(other: {file: {codes_column: col_codes}})
|
80
|
-
end
|
81
|
-
|
82
|
-
desc = "Creates a CSV with the paths to each tag"
|
83
|
-
cases.add("-create-tag-paths", :other, desc, case_name: "create-tag-paths")
|
84
|
-
|
85
|
-
desc = "Creates a JSON file with the tagtree from a CSV file"
|
86
|
-
cases.add("-csv-to-tree", :other, desc, case_name: "csv-to-tree") do |session, options, usecase|
|
87
|
-
file = SCR.get_file("-csv-to-tree", required: true, should_exist: true)
|
88
|
-
options.deep_merge!(source: {file: file})
|
89
|
-
end
|
90
|
-
|
91
22
|
desc = "Forces a change of email in the same org. It won't succeed if email taken by an org member user"
|
92
23
|
cases.add("-change-email-from", :sync, desc, case_name: "change-email")
|
93
24
|
|
@@ -95,12 +26,12 @@ ASSETS.cli.config do |cnf|
|
|
95
26
|
cases.add("-switch-supervisor", :transform, desc, case_name: "switch-supervisor") do |people, session, options|
|
96
27
|
unless options[:super]&.key?(:old)
|
97
28
|
msg = "You must specify an -old-super to target whose supervisor is changing"
|
98
|
-
session.
|
29
|
+
session.log(:error) { msg }
|
99
30
|
exit(1)
|
100
31
|
end
|
101
32
|
unless options[:super]&.key?(:new)
|
102
33
|
msg = "You must specify the -new-super id. To reset to nil the supervisor, please, specify nil."
|
103
|
-
session.
|
34
|
+
session.log(:error) { msg }
|
104
35
|
exit(1)
|
105
36
|
end
|
106
37
|
end.add_option("-old-super", "The supervisor id to be replaced on the subordinates") do |options|
|
@@ -115,59 +46,13 @@ ASSETS.cli.config do |cnf|
|
|
115
46
|
end
|
116
47
|
end
|
117
48
|
|
118
|
-
desc
|
49
|
+
desc = "Input file dump into a CSV as is."
|
119
50
|
cases.add("-entries-to-csv", :import, desc, case_name: "entries-to-csv")
|
120
51
|
.add_option("-out") do |options|
|
121
52
|
file = SCR.get_file("-out")
|
122
53
|
options.deep_merge!(export: {file: file})
|
123
54
|
end
|
124
55
|
|
125
|
-
desc = "Usage '-org-data-convert backup.json -restore-db-from'."
|
126
|
-
desc += " Transforms an input .json file to the values of the destination environment "
|
127
|
-
desc += " (names missmatch won't solve: i.e. usergroups)"
|
128
|
-
cases.add("-org-data-convert", :import, desc, case_name: "org-data-convert") do |input, session, options|
|
129
|
-
unless input && input.is_a?(Eco::API::Organization::People)
|
130
|
-
file = SCR.get_file("-org-data-convert", required: true)
|
131
|
-
input = Eco::API::Organization::People.new(JSON.parse(File.read(file)))
|
132
|
-
session.logger.info("Source DB: loaded #{input.length} entries.")
|
133
|
-
end
|
134
|
-
|
135
|
-
unless options[:source_enviro]
|
136
|
-
session.logger.error("You need to specify a -source-enviro for the conversion to work out")
|
137
|
-
exit(1)
|
138
|
-
end
|
139
|
-
|
140
|
-
end.add_option("-source-enviro", "The defined -source-enviro API configuration that the backup file was generated from") do |options|
|
141
|
-
options.merge!(source_enviro: SCR.get_arg("-source-enviro", with_param: true))
|
142
|
-
end.add_option("-ignore-missing-policy-groups", "Prevents the script to crash when backup file has missing usergroups in the org") do |options|
|
143
|
-
options.deep_merge!(ignore: {missing: {policy_groups: true}})
|
144
|
-
end
|
145
|
-
|
146
|
-
desc = "Restores the people manager by using a backup.json file"
|
147
|
-
cases.add("-restore-db-from", :sync, desc, case_name: "restore-db") do |input, people, session, options|
|
148
|
-
unless input && input.is_a?(Eco::API::Organization::People)
|
149
|
-
file = SCR.get_file("-restore-db-from", required: true)
|
150
|
-
input = Eco::API::Organization::People.new(JSON.parse(File.read(file)))
|
151
|
-
session.logger.info("Source DB: loaded #{input.length} entries.")
|
152
|
-
end
|
153
|
-
end.add_option("-include-delete", "If it should DELETE people that do not exist in the backup file") do |options|
|
154
|
-
options.deep_merge!(include: {delete: true})
|
155
|
-
end.add_option("-include-create", "If it should CREATE people that do not exist in the people manager") do |options|
|
156
|
-
options.deep_merge!(include: {create: true})
|
157
|
-
end
|
158
|
-
|
159
|
-
desc = "Re-sends invites to all filtered users that have not accepted the invite as yet"
|
160
|
-
cases.add("-reinvite", :transform, desc, case_name: "reinvite")
|
161
|
-
.add_option("-force", "If also send an invite email to those that have accepted the invite") do |options|
|
162
|
-
options.deep_merge!(force: {invite: true})
|
163
|
-
end
|
164
|
-
|
165
|
-
desc = "Re-sends invites to target users that have not accepted the invite as yet"
|
166
|
-
cases.add("-reinvite-from", :sync, desc, case_name: "reinvite")
|
167
|
-
.add_option("-force", "If also send an invite email to those that have accepted the invite") do |options|
|
168
|
-
options.deep_merge!(force: {invite: true})
|
169
|
-
end
|
170
|
-
|
171
56
|
desc = "Clears the `permissions_custom`, provided that Policy Group abilities alone apply."
|
172
57
|
desc += " Please be mindfull if you use this option (there may be users that have been upgraded in ad-hoc manner)."
|
173
58
|
cases.add("-clear-abilities", :transform, desc, case_name: "clear-abilities")
|
@@ -219,7 +104,9 @@ ASSETS.cli.config do |cnf|
|
|
219
104
|
options.deep_merge!(export: {file: {name: file || "RegisterExport.csv", format: :csv}})
|
220
105
|
|
221
106
|
unless options.dig(:source, :register_id)
|
222
|
-
session.
|
107
|
+
session.log(:error) {
|
108
|
+
"You should specify the target register id"
|
109
|
+
}
|
223
110
|
exit(1)
|
224
111
|
end
|
225
112
|
end.add_option("-register-id", "Target register id") do |options|
|
@@ -38,6 +38,7 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
|
|
38
38
|
|
39
39
|
wf_in.on(:filter) do |_wf_if, io|
|
40
40
|
next unless input && !input.empty?
|
41
|
+
|
41
42
|
io.new(input: cli.config.input_filters.process(io: io))
|
42
43
|
end
|
43
44
|
end
|
@@ -47,6 +48,7 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
|
|
47
48
|
cases_with_people = cli.config.usecases.active(io: io).select do |usecase, _data|
|
48
49
|
io.class.people_required?(usecase.type)
|
49
50
|
end
|
51
|
+
|
50
52
|
next if cases_with_people.empty? && !options.dig(:people, :get)
|
51
53
|
|
52
54
|
io.new(people: cli.config.people(io: io))
|
@@ -78,7 +80,7 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
|
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
81
|
-
wf.before(:launch_jobs) do |_wf_jobs,
|
83
|
+
wf.before(:launch_jobs) do |_wf_jobs, _io|
|
82
84
|
available_args = cli.config.available_option_args
|
83
85
|
SCR.stop_on_unknown!(all_available: available_args)
|
84
86
|
end
|
@@ -95,7 +97,7 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
|
|
95
97
|
wf_post.skip!
|
96
98
|
log(:info) {
|
97
99
|
msg = "Although there are post_launch cases, they will NOT be RUN"
|
98
|
-
msg
|
100
|
+
msg << ", because we are in dry-run (simulate)." if options[:dry_run]
|
99
101
|
msg
|
100
102
|
}
|
101
103
|
next
|
@@ -109,9 +111,9 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
|
|
109
111
|
log(:info) {
|
110
112
|
msg = "Although there are post_launch cases, data will not be refreshed before their run"
|
111
113
|
if io.options[:dry_run]
|
112
|
-
msg
|
114
|
+
msg << ", because we are in dry-run (simulate)."
|
113
115
|
elsif !partial_update
|
114
|
-
msg
|
116
|
+
msg << ", because it is not a partial update (-get-partial option not present)."
|
115
117
|
end
|
116
118
|
msg
|
117
119
|
}
|
data/lib/eco/csv/split.rb
CHANGED
@@ -21,11 +21,13 @@ module Eco
|
|
21
21
|
def copy_count
|
22
22
|
@copy_count ||= 0
|
23
23
|
end
|
24
|
+
attr_writer :copy_count
|
24
25
|
|
25
26
|
# @return [Integer] number of total input rows
|
26
27
|
def total_count
|
27
28
|
@total_count ||= 0
|
28
29
|
end
|
30
|
+
attr_writer :total_count
|
29
31
|
|
30
32
|
# @return [Array<String>] list of created files
|
31
33
|
def out_files
|
data/lib/eco/csv/table.rb
CHANGED
@@ -5,6 +5,7 @@ module Eco
|
|
5
5
|
# - when `Array<Array>` => all `rows` as arrays where first array is the **header**
|
6
6
|
def initialize(input)
|
7
7
|
super(to_rows_array(input))
|
8
|
+
|
8
9
|
delete_if do |row|
|
9
10
|
values = row.fields
|
10
11
|
values.all?(&:nil?) || values.map(&:to_s).all?(&:empty?)
|
@@ -21,6 +22,7 @@ module Eco
|
|
21
22
|
row[header] = value.empty?? nil : value
|
22
23
|
end
|
23
24
|
end
|
25
|
+
|
24
26
|
self
|
25
27
|
end
|
26
28
|
|
@@ -41,9 +43,11 @@ module Eco
|
|
41
43
|
# @return [Eco::CSV::Table]
|
42
44
|
def transform_headers
|
43
45
|
cols = columns
|
46
|
+
|
44
47
|
cols.each do |col|
|
45
48
|
col[0] = yield(col.first)
|
46
49
|
end
|
50
|
+
|
47
51
|
columns_to_table(cols)
|
48
52
|
end
|
49
53
|
|
@@ -70,6 +74,7 @@ module Eco
|
|
70
74
|
end
|
71
75
|
end
|
72
76
|
end
|
77
|
+
|
73
78
|
self.class.new(out_rows)
|
74
79
|
end
|
75
80
|
|
@@ -83,6 +88,7 @@ module Eco
|
|
83
88
|
def transform_values
|
84
89
|
transformed_rows = rows.map do |row|
|
85
90
|
res = yield(row)
|
91
|
+
|
86
92
|
case res
|
87
93
|
when Array
|
88
94
|
::CSV::Row.new(row.headers, res)
|
@@ -90,6 +96,7 @@ module Eco
|
|
90
96
|
res
|
91
97
|
end
|
92
98
|
end
|
99
|
+
|
93
100
|
self.class.new(transformed_rows)
|
94
101
|
end
|
95
102
|
|
@@ -136,6 +143,7 @@ module Eco
|
|
136
143
|
def add_column(header_name, pos: -1)
|
137
144
|
header_name = header_name.to_s.strip
|
138
145
|
raise ArgumentError, "header_name can't be blank" if header_name.empty?
|
146
|
+
|
139
147
|
new_col = Array.new(length).unshift(header_name)
|
140
148
|
columns_to_table(columns.insert(pos, new_col))
|
141
149
|
end
|
@@ -146,6 +154,7 @@ module Eco
|
|
146
154
|
# @return [Eco::CSV::Table] with a new column named `name` with the row number
|
147
155
|
def add_index_column(header_name = 'idx', pos: 0)
|
148
156
|
header_name = header_name.to_s.strip
|
157
|
+
|
149
158
|
add_column(header_name, pos: pos).tap do |table|
|
150
159
|
table.each.with_index do |row, idx|
|
151
160
|
row[header_name] = idx + 2
|
@@ -163,6 +172,7 @@ module Eco
|
|
163
172
|
# It removes all rows where all columns' values are the same
|
164
173
|
def delete_duplicates!
|
165
174
|
unique_rows = []
|
175
|
+
|
166
176
|
by_row!.delete_if do |row|
|
167
177
|
unique_rows.any? {|done| equal_rows?(row, done)}.tap do |found|
|
168
178
|
unique_rows << row unless found
|
@@ -218,6 +228,7 @@ module Eco
|
|
218
228
|
def columns_to_table(columns_array)
|
219
229
|
rows_data = columns_array.transpose
|
220
230
|
return self.class.new(rows_data) if rows_data.length.positive?
|
231
|
+
|
221
232
|
raise ArgumentError, "Expecting 'columns_array' to at least have header. Given: #{columns_array}"
|
222
233
|
end
|
223
234
|
|
@@ -232,6 +243,7 @@ module Eco
|
|
232
243
|
when Enumerable
|
233
244
|
data = data.dup.compact
|
234
245
|
return data unless data.count.positive?
|
246
|
+
|
235
247
|
sample = data.first
|
236
248
|
|
237
249
|
case sample
|
@@ -264,6 +276,7 @@ module Eco
|
|
264
276
|
|
265
277
|
def if_array_to_pipe_string(value)
|
266
278
|
return value unless value.is_a?(Array)
|
279
|
+
|
267
280
|
value.join('|')
|
268
281
|
end
|
269
282
|
end
|
@@ -4,7 +4,7 @@ module Eco
|
|
4
4
|
module Encoding
|
5
5
|
include Eco::Language::AuxiliarLogger
|
6
6
|
|
7
|
-
BOM_BYTES = [239, 187, 191]
|
7
|
+
BOM_BYTES = [239, 187, 191].freeze
|
8
8
|
|
9
9
|
def has_bom?(path)
|
10
10
|
return false if !path || file_empty?(path)
|
@@ -16,9 +16,10 @@ module Eco
|
|
16
16
|
|
17
17
|
def get_file_content_with_encoding(file, encoding: nil)
|
18
18
|
encoding ||= scoped_encoding(file)
|
19
|
+
|
19
20
|
unless !encoding || encoding == 'utf-8'
|
20
21
|
msg = "File encoding: '#{encoding}'"
|
21
|
-
|
22
|
+
log(:debug) { msg }
|
22
23
|
puts msg
|
23
24
|
end
|
24
25
|
|
@@ -29,7 +30,9 @@ module Eco
|
|
29
30
|
else
|
30
31
|
content = File.read(file, encoding: encoding)
|
31
32
|
end
|
32
|
-
|
33
|
+
|
34
|
+
return unless content
|
35
|
+
|
33
36
|
content = content.encode("utf-8") unless encoding.include?('utf-8')
|
34
37
|
content
|
35
38
|
end
|
@@ -42,6 +45,7 @@ module Eco
|
|
42
45
|
content = content.sub(bom, '')
|
43
46
|
content.force_encoding('utf-8')
|
44
47
|
end
|
48
|
+
|
45
49
|
content
|
46
50
|
end
|
47
51
|
|
@@ -52,21 +56,24 @@ module Eco
|
|
52
56
|
# Gives the parameter as it should
|
53
57
|
def scoped_encoding(path)
|
54
58
|
unless file_exists?(path)
|
55
|
-
|
59
|
+
log(:error) { "File does not exist: #{path}" }
|
56
60
|
return nil
|
57
61
|
end
|
62
|
+
|
58
63
|
encoding ||= encoding(path)
|
59
|
-
encoding =
|
64
|
+
encoding = "#{encoding}|utf-8" if encoding == "bom"
|
60
65
|
encoding
|
61
66
|
end
|
62
67
|
|
63
68
|
def file_exists?(file)
|
64
|
-
return false
|
65
|
-
|
69
|
+
return false unless file
|
70
|
+
|
71
|
+
File.exist?(file) || File.exist?(File.expand_path(file))
|
66
72
|
end
|
67
73
|
|
68
74
|
def file_empty?(path)
|
69
|
-
return true
|
75
|
+
return true unless File.file?(path)
|
76
|
+
|
70
77
|
File.zero?(path)
|
71
78
|
end
|
72
79
|
end
|
@@ -30,11 +30,15 @@ module Eco
|
|
30
30
|
replacement = "<#{bytes.unpack1('H*')}>"
|
31
31
|
|
32
32
|
if tolerance <= 0
|
33
|
-
|
33
|
+
log(:error) {
|
34
|
+
"There were more than 5 encoding errors in the file '#{file}'."
|
35
|
+
}
|
34
36
|
return content
|
35
37
|
else
|
36
38
|
tolerance -= 1
|
37
|
-
|
39
|
+
log(:error) {
|
40
|
+
"Encoding problem in file '#{file}': '#{replacement}'."
|
41
|
+
}
|
38
42
|
replacement
|
39
43
|
end
|
40
44
|
end
|
@@ -48,8 +48,10 @@ module Eco
|
|
48
48
|
# between `src_1` and `src_2`.
|
49
49
|
def diff_attrs
|
50
50
|
return (@diff_attrs = []) if new? || del?
|
51
|
+
|
51
52
|
@diff_attrs ||= all_compared_attrs.each_with_object([]) do |kattr, out|
|
52
53
|
next unless comparable_attr?(kattr)
|
54
|
+
|
53
55
|
out << kattr unless eq?(attr_prev(kattr), attr(kattr))
|
54
56
|
end
|
55
57
|
end
|
@@ -71,6 +73,7 @@ module Eco
|
|
71
73
|
def diff_attr?(attr)
|
72
74
|
return true if new?
|
73
75
|
return true if del?
|
76
|
+
|
74
77
|
diff_attrs.include?(attr.to_s)
|
75
78
|
end
|
76
79
|
|
@@ -80,6 +83,7 @@ module Eco
|
|
80
83
|
target_attrs = [key] | all_compared_attrs
|
81
84
|
return slice_attrs(src_2, *target_attrs) if new?
|
82
85
|
return slice_attrs(src_1, key) if del?
|
86
|
+
|
83
87
|
slice_attrs(src_2, key, *diff_attrs)
|
84
88
|
end
|
85
89
|
|
@@ -109,6 +113,7 @@ module Eco
|
|
109
113
|
attr = attr.to_s
|
110
114
|
return false unless all_compared_attrs.include?(attr)
|
111
115
|
return true unless self.class.compared_attr_when_present?(attr)
|
116
|
+
|
112
117
|
key_present_in_both?(attr)
|
113
118
|
end
|
114
119
|
|
@@ -28,6 +28,7 @@ class Eco::Data::Locations::NodeDiff
|
|
28
28
|
@diffs ||= super.select do |dff|
|
29
29
|
# discard entries that are to be inserted and archived at the same time
|
30
30
|
next false if dff.insert? && dff.archive?(validate: false)
|
31
|
+
|
31
32
|
dff.unarchive? || dff.id_name? || dff.insert? ||
|
32
33
|
dff.move? || dff.archive?
|
33
34
|
end
|
@@ -67,32 +68,42 @@ class Eco::Data::Locations::NodeDiff
|
|
67
68
|
def diffs_summary # rubocop:disable Metrics/AbcSize
|
68
69
|
comp = "(#{source_2.count} input nodes VS #{source_1.count} live nodes)"
|
69
70
|
return "There were no differences identified #{comp}" if diffs.empty?
|
71
|
+
|
70
72
|
msg = []
|
73
|
+
|
71
74
|
msg << "Identified #{diffs.count} differences #{comp}:"
|
72
75
|
msg << when_present(insert) do |count|
|
73
76
|
" • #{count} nodes to insert"
|
74
77
|
end
|
78
|
+
|
75
79
|
msg << when_present(update) do |count|
|
76
80
|
" • #{count} nodes to update"
|
77
81
|
end
|
82
|
+
|
78
83
|
msg << when_present(unarchive) do |count|
|
79
84
|
" • #{count} nodes to unarchive (includes ancestors of target nodes)"
|
80
85
|
end
|
86
|
+
|
81
87
|
msg << when_present(id) do |count|
|
82
88
|
" • #{count} nodes to change id\n"
|
83
89
|
end
|
90
|
+
|
84
91
|
msg << when_present(name) do |count|
|
85
92
|
" • #{count} nodes to change name"
|
86
93
|
end
|
94
|
+
|
87
95
|
msg << when_present(classifications) do |count|
|
88
96
|
" • #{count} nodes to change classifications"
|
89
97
|
end
|
98
|
+
|
90
99
|
msg << when_present(move) do |count|
|
91
100
|
" • #{count} nodes to move"
|
92
101
|
end
|
102
|
+
|
93
103
|
msg << when_present(archive) do |count|
|
94
104
|
" • #{count} nodes to archive"
|
95
105
|
end
|
106
|
+
|
96
107
|
msg.compact.join("\n")
|
97
108
|
end
|
98
109
|
|
@@ -108,8 +119,10 @@ class Eco::Data::Locations::NodeDiff
|
|
108
119
|
|
109
120
|
def when_present(list, default = nil)
|
110
121
|
raise ArgumentError, "Expecting block but not given" unless block_given?
|
122
|
+
|
111
123
|
count = list.count
|
112
124
|
return yield(count) if count&.positive?
|
125
|
+
|
113
126
|
default
|
114
127
|
end
|
115
128
|
|
@@ -50,12 +50,14 @@ module Eco::Data::Locations
|
|
50
50
|
def id_name?
|
51
51
|
return true if id?
|
52
52
|
return true if name?
|
53
|
+
|
53
54
|
classifications?
|
54
55
|
end
|
55
56
|
|
56
57
|
# Has the parent id changed?
|
57
58
|
def move?
|
58
59
|
return false unless update?
|
60
|
+
|
59
61
|
parent_id?
|
60
62
|
end
|
61
63
|
|
@@ -72,6 +74,7 @@ module Eco::Data::Locations
|
|
72
74
|
return true if marked_for_unarchive?
|
73
75
|
return false if archived
|
74
76
|
return false unless update?
|
77
|
+
|
75
78
|
archived?
|
76
79
|
end
|
77
80
|
|
@@ -86,6 +89,7 @@ module Eco::Data::Locations
|
|
86
89
|
raise msg if validate && archived && insert?
|
87
90
|
|
88
91
|
return true if del?
|
92
|
+
|
89
93
|
archived
|
90
94
|
end
|
91
95
|
end
|
@@ -70,6 +70,7 @@ module Eco::Data::Locations
|
|
70
70
|
|
71
71
|
def classifications
|
72
72
|
return [] unless (al = actual_level).positive?
|
73
|
+
|
73
74
|
original_headers[al - 1]
|
74
75
|
end
|
75
76
|
|
@@ -111,8 +112,10 @@ module Eco::Data::Locations
|
|
111
112
|
# Requires that all upper levels (lower positions) are filled-in
|
112
113
|
def common_level_with(other)
|
113
114
|
return nil unless other
|
115
|
+
|
114
116
|
otags_array = other.tags_array.compact
|
115
117
|
stags_array = tags_array.compact
|
118
|
+
|
116
119
|
raise "Missing lower levels for #{other.id}: #{other.tags_array.pretty_inspect}" unless other.highest_levels_set?
|
117
120
|
raise "Missing lower levels for #{id}: #{tags_array.pretty_inspect}" unless highest_levels_set?
|
118
121
|
|
@@ -174,6 +177,7 @@ module Eco::Data::Locations
|
|
174
177
|
def highest_levels_set?
|
175
178
|
return true if raw_level == 1
|
176
179
|
return true unless raw_prev_empty_level?
|
180
|
+
|
177
181
|
!!@highest_levels_set
|
178
182
|
end
|
179
183
|
|
@@ -194,10 +198,12 @@ module Eco::Data::Locations
|
|
194
198
|
target = i.to_a
|
195
199
|
when Integer
|
196
200
|
return false unless i >= 1 && i <= tag_attrs_count
|
201
|
+
|
197
202
|
target = Array(i..tag_attrs_count)
|
198
203
|
else
|
199
204
|
return false
|
200
205
|
end
|
206
|
+
|
201
207
|
return false if target.empty?
|
202
208
|
|
203
209
|
target.each do |n|
|
data/lib/eco/version.rb
CHANGED