opensecret 0.0.2 → 0.0.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/Gemfile +4 -0
- data/README.md +2 -2
- data/bin/opensecret +3 -6
- data/lib/opensecret-domain.ini +23 -0
- data/lib/opensecret.rb +30 -2
- data/lib/opensecret/additions/array.rb +117 -0
- data/lib/opensecret/additions/dir.rb +35 -0
- data/lib/opensecret/additions/string.rb +312 -0
- data/lib/opensecret/commons/eco.cmdline.rb +446 -0
- data/lib/opensecret/commons/eco.faculty.rb +364 -0
- data/lib/opensecret/commons/eco.system.rb +437 -0
- data/lib/opensecret/commons/eco.systems.rb +98 -0
- data/lib/opensecret/{safe.rb → delegate.rb} +4 -2
- data/lib/opensecret/eco.do.rb +46 -0
- data/lib/opensecret/executors/crypt.keys/crypt.keys.ini +79 -0
- data/lib/opensecret/executors/crypt.keys/crypt.keys.rb +68 -0
- data/lib/opensecret/executors/decrypt/decrypt.ini +64 -0
- data/lib/opensecret/executors/decrypt/decrypt.rb +49 -0
- data/lib/opensecret/executors/encrypt/encrypt.ini +55 -0
- data/lib/opensecret/executors/encrypt/encrypt.rb +82 -0
- data/lib/opensecret/factbase/hub-runtime.ini +123 -0
- data/lib/opensecret/factbase/known-hosts.ini +75 -0
- data/lib/opensecret/factbase/published.facts/blobbolicious-facts.ini +553 -0
- data/lib/opensecret/factbase/published.facts/credential-facts.ini +40 -0
- data/lib/opensecret/factbase/published.facts/infrastructure-facts.ini +63 -0
- data/lib/opensecret/factbase/readme.md +24 -0
- data/lib/opensecret/factbase/retired.facts/maven.database.ide.facts.ini +127 -0
- data/lib/opensecret/factbase/retired.facts/s3-upload-block-facts.ini +17 -0
- data/lib/opensecret/plugins.io/cipher/crypto.rb +174 -0
- data/lib/opensecret/plugins.io/error/eco.exceptions.rb +24 -0
- data/lib/opensecret/plugins.io/facts/fact.chars.rb +66 -0
- data/lib/opensecret/plugins.io/facts/fact.factor.rb +156 -0
- data/lib/opensecret/plugins.io/facts/fact.locator.rb +105 -0
- data/lib/opensecret/plugins.io/facts/fact.reader.rb +137 -0
- data/lib/opensecret/plugins.io/facts/fact.tree.rb +661 -0
- data/lib/opensecret/plugins.io/file/file.rb +483 -0
- data/lib/opensecret/plugins.io/git/git.flow.rb +388 -0
- data/lib/opensecret/plugins.io/logs/log.object.rb +89 -0
- data/lib/opensecret/plugins.io/logs/logging.rb +203 -0
- data/lib/opensecret/plugins.io/time/time.stamp.rb +425 -0
- data/lib/opensecret/version.rb +2 -2
- data/opensecret.gemspec +8 -13
- metadata +68 -18
@@ -0,0 +1,483 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# -- --------------------------------------------------------------- -- #
|
4
|
+
# -- File facts are placeholders (keys in effect) just begging to be -- #
|
5
|
+
# -- replaced by values sourced from some sort of map. This software -- #
|
6
|
+
# -- centres around the DevOps fact replacement placeholder pattern. -- #
|
7
|
+
# -- --------------------------------------------------------------- -- #
|
8
|
+
class Files
|
9
|
+
#### ==> ===================================================================================
|
10
|
+
#### ==> ===================================================================================
|
11
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
12
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
13
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
14
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
15
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
16
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
17
|
+
#### ==> Name this class FindReplace or simply just Replace => Replace.contains? Replace.do
|
18
|
+
#### ==> ===================================================================================
|
19
|
+
#### ==> ===================================================================================
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
## --- ---------------------------------------------------------------------- --- #
|
24
|
+
## --- How to Use File to extract different parts of an [absolute] file path. --- #
|
25
|
+
## --- ---------------------------------------------------------------------- --- #
|
26
|
+
### File Names ====] file = "/path/to/xyz.mp4"
|
27
|
+
### File Names ====] comp = File.basename file # => "xyz.mp4"
|
28
|
+
### File Names ====] extn = File.extname file # => ".mp4"
|
29
|
+
### File Names ====] name = File.basename file, extn # => "xyz"
|
30
|
+
### File Names ====] path = File.dirname file # => "/path/to"
|
31
|
+
## --- ---------------------------------------------------------------------- --- #
|
32
|
+
|
33
|
+
|
34
|
+
# --
|
35
|
+
# -- Scan every file in directory for placeholder keys within the
|
36
|
+
# -- parameter map and replace them with the corresponding value.
|
37
|
+
# -- Not Recursive => the scan does [not] recurse into folders
|
38
|
+
# --
|
39
|
+
# -- ----------------------------------
|
40
|
+
# -- Replacing Betty (Nested Replace)
|
41
|
+
# -- ----------------------------------
|
42
|
+
# --
|
43
|
+
# -- "GoBBetBettytyettyne" => "Gone"
|
44
|
+
# --
|
45
|
+
# -- A nested replace is done up to approximately 5 levels deep.
|
46
|
+
# -- So replacing "Betty" from the above string does [NOT] produce
|
47
|
+
# -- "GoBBettyettyne". The string becomes "Gone".
|
48
|
+
# --
|
49
|
+
# -- -----------
|
50
|
+
# -- Parameters
|
51
|
+
# -- -----------
|
52
|
+
# -- fact_map : driving [placeholder] => [value] map
|
53
|
+
# -- replace_dir : dir subject of the scan and replace
|
54
|
+
# --
|
55
|
+
def self.find_replace fact_map, replace_folder
|
56
|
+
|
57
|
+
log.info(ere){ "#-- --------------------------------------------------------- #" }
|
58
|
+
log.info(ere){ "#-- File changing in #{File.basename replace_folder}" }
|
59
|
+
log.info(ere){ "#-- #{replace_folder}" }
|
60
|
+
log.info(ere){ "#-- --------------------------------------------------------- #" }
|
61
|
+
|
62
|
+
# -- ------------------------------------------------------------------------------ -- #
|
63
|
+
# -- Iterate to substitute matched strings in file with their corresponding values. -- #
|
64
|
+
# -- ------------------------------------------------------------------------------ -- #
|
65
|
+
Dir.foreach( replace_folder ) do | file_name |
|
66
|
+
|
67
|
+
file_path = File.join replace_folder, file_name
|
68
|
+
next if File.directory? file_path
|
69
|
+
next if File.extname(file_path).eql? ".log"
|
70
|
+
|
71
|
+
nested_key_replace fact_map, file_path
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
log.info(ere){ "#-- --------------------------------------------------------- #" }
|
76
|
+
log.info(ere){ "#-- Done changing files in #{File.basename replace_folder}" }
|
77
|
+
log.info(ere){ "#-- --------------------------------------------------------- #" }
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
#--
|
82
|
+
#-- Using the parameter [file] [replace] any occurence
|
83
|
+
#-- of any [key] found in the parameter [map] with the
|
84
|
+
#-- corresponding mapped key [value].
|
85
|
+
#--
|
86
|
+
#-- -----------------------------------
|
87
|
+
#-- [Nested Replace]
|
88
|
+
# -- Replacing Betty (Nested Replace)
|
89
|
+
# -- ----------------------------------
|
90
|
+
# --
|
91
|
+
# -- "GoBBetBettytyettyne" => "Gone"
|
92
|
+
# --
|
93
|
+
# -- A nested replace is done up to approximately 5 levels deep.
|
94
|
+
# -- So replacing "Betty" from the above string does [NOT] produce
|
95
|
+
# -- "GoBBettyettyne". The string becomes "Gone".
|
96
|
+
# --
|
97
|
+
def self.nested_key_replace source_map, filepath
|
98
|
+
|
99
|
+
for i in 1..5
|
100
|
+
file_changed = key_replace source_map, filepath
|
101
|
+
return unless file_changed
|
102
|
+
log.info(ere){ "#-- --------------------------------------------------------- #" }
|
103
|
+
log.info(ere){ "#-- File #{File.basename filepath} has been changed" }
|
104
|
+
log.info(ere){ "#-- --------------------------------------------------------- #" }
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
#--
|
110
|
+
#-- Using the parameter [file] [replace] any occurence
|
111
|
+
#-- of any [key] found in the parameter [map] with the
|
112
|
+
#-- corresponding mapped key [value].
|
113
|
+
#--
|
114
|
+
#-- Side Effect => If at least one replacement occured this
|
115
|
+
#-- method returns true, else false.
|
116
|
+
#--
|
117
|
+
def self.key_replace source_map, filepath
|
118
|
+
|
119
|
+
replace_happened = false
|
120
|
+
|
121
|
+
source_map.each do |theKey, theValue|
|
122
|
+
|
123
|
+
next unless has_string? filepath, theKey
|
124
|
+
factorize theKey, theValue, filepath
|
125
|
+
replace_happened = true
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
return replace_happened
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
#--
|
136
|
+
#-- Produce a map of every "recursive" file sitting under
|
137
|
+
#-- any and all of the parameter directories array.
|
138
|
+
#--
|
139
|
+
#-- Harboured folders are traversed but folder names are
|
140
|
+
#-- excluded from the resulting map.
|
141
|
+
#--
|
142
|
+
#-- The key/value structure of the map is
|
143
|
+
#--
|
144
|
+
#-- key => simple filename
|
145
|
+
#-- value => (abs) folder path
|
146
|
+
#--
|
147
|
+
#-- --------------------------------
|
148
|
+
#-- Filename NOT UNIQUE Exception
|
149
|
+
#-- --------------------------------
|
150
|
+
#--
|
151
|
+
#-- Simple filename UNIQUENESS must prevail.
|
152
|
+
#--
|
153
|
+
#-- If the same base filename is found in any part or level
|
154
|
+
#-- of the directory trees under the every parameter parent
|
155
|
+
#-- folder - an exception will be thrown.
|
156
|
+
#--
|
157
|
+
def self.in_folders parent_folders
|
158
|
+
|
159
|
+
files_map = {}
|
160
|
+
|
161
|
+
parent_folders.each do |parent_folder|
|
162
|
+
|
163
|
+
log.info(ere) { "Create map of files under #{nickname parent_folder}" }
|
164
|
+
Throw.if_not_exists parent_folder
|
165
|
+
|
166
|
+
Dir["#{parent_folder}/**/*"].each do |child_file|
|
167
|
+
|
168
|
+
next if File.directory? child_file
|
169
|
+
filename = File.basename child_file
|
170
|
+
foldername = File.dirname child_file
|
171
|
+
log.info(ere) { " #{filename} => #{nickname foldername}" }
|
172
|
+
error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
|
173
|
+
raise RuntimeError.new error_str if files_map.has_key? filename
|
174
|
+
files_map.store filename, foldername
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
return files_map
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
#--
|
186
|
+
#-- Find files of a given type (extension) that exist
|
187
|
+
#-- recursively under a folder.
|
188
|
+
#--
|
189
|
+
#-- --------------------------------
|
190
|
+
#-- Filename NOT UNIQUE Exception
|
191
|
+
#-- --------------------------------
|
192
|
+
#--
|
193
|
+
#-- Simple filename UNIQUENESS must prevail.
|
194
|
+
#--
|
195
|
+
#-- If the same base filename is found in any part or level
|
196
|
+
#-- of the directory trees under the every parameter parent
|
197
|
+
#-- folder - an exception will be thrown.
|
198
|
+
#--
|
199
|
+
#-- ------------
|
200
|
+
#-- Parameters
|
201
|
+
#-- ------------
|
202
|
+
#--
|
203
|
+
#-- base_folder => the top-level folder to search
|
204
|
+
#-- dir at (abs) path must exist
|
205
|
+
#--
|
206
|
+
#-- file_extn => extension of interesting files
|
207
|
+
#-- including the leading [period].
|
208
|
+
#-- (send ".exe" for exe files)
|
209
|
+
#-- (send ".md" for markdown files)
|
210
|
+
#--
|
211
|
+
#-- ------------
|
212
|
+
#-- Map Returned
|
213
|
+
#-- ------------
|
214
|
+
#--
|
215
|
+
#-- Returns a { filename => rel_path } map of the matching
|
216
|
+
#-- files in the folder. The map
|
217
|
+
#--
|
218
|
+
#-- keys => simple filename without extension
|
219
|
+
#-- values => relative path from the base folder
|
220
|
+
#--
|
221
|
+
def self.to_name_path_map base_folder, file_extn
|
222
|
+
|
223
|
+
files_map = {}
|
224
|
+
|
225
|
+
Dir["#{base_folder}/**/*#{file_extn}"].each do |filepath|
|
226
|
+
|
227
|
+
next if File.directory? filepath
|
228
|
+
ext_error = "File extension not [#{file_extn}] in => #{nickname filepath}"
|
229
|
+
raise RuntimeError.new(ext_error) unless File.extname(filepath).eql? "#{file_extn}"
|
230
|
+
|
231
|
+
filename = File.basename filepath
|
232
|
+
|
233
|
+
error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
|
234
|
+
raise RuntimeError.new error_str if files_map.has_key? filename
|
235
|
+
files_map.store filename, filepath
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
return files_map
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
#--
|
245
|
+
#-- Return a new map with the values folder path
|
246
|
+
#-- forwarded by one level
|
247
|
+
#--
|
248
|
+
#-- If the map contains the below
|
249
|
+
#--
|
250
|
+
#-- {
|
251
|
+
#-- file1 => user/docs/pdfs,
|
252
|
+
#-- file2 => user/docs/pdfs/good,
|
253
|
+
#-- file3 => user/docs/pdfs/bad
|
254
|
+
#-- }
|
255
|
+
#--
|
256
|
+
#-- This method will return a map like this
|
257
|
+
#--
|
258
|
+
#-- {
|
259
|
+
#-- file1 => docs/pdfs,
|
260
|
+
#-- file2 => docs/pdfs/good,
|
261
|
+
#-- file3 => docs/pdfs/bad
|
262
|
+
#-- }
|
263
|
+
#--
|
264
|
+
#-- The values part has been forwarded by one level.
|
265
|
+
#--
|
266
|
+
def self.forwarded_path files_map
|
267
|
+
|
268
|
+
changed_map = {}
|
269
|
+
|
270
|
+
files_map.each do |the_name, the_old_path|
|
271
|
+
the_new_path = the_old_path.split("/")[1..-1].join("/")
|
272
|
+
changed_map.store the_name, the_new_path
|
273
|
+
log.info(ere){ "Forwarded from #{the_old_path} to #{the_new_path}" }
|
274
|
+
end
|
275
|
+
|
276
|
+
return changed_map
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
#--
|
282
|
+
#-- Path stripper expects the path in the first parameter
|
283
|
+
#-- to start with the path in the second parameter.
|
284
|
+
#--
|
285
|
+
#-- It then returns the first parameter path with the
|
286
|
+
#-- leading path stripped out.
|
287
|
+
#--
|
288
|
+
#-- ---------------------------
|
289
|
+
#-- Strip Leading Path Example
|
290
|
+
#-- ---------------------------
|
291
|
+
#--
|
292
|
+
#-- 1st param path = /home/joe/docs/pdfs/websites
|
293
|
+
#-- 2nd param path = /home/joe/docs
|
294
|
+
#-- Returned Path = pdfs/websites
|
295
|
+
#--
|
296
|
+
#-- ---------------------------------
|
297
|
+
#-- The Middle Separator is Stripped
|
298
|
+
#-- ---------------------------------
|
299
|
+
#--
|
300
|
+
#-- Note above that the middle separator is stripped
|
301
|
+
#-- so the returned string has no leading separator.
|
302
|
+
#--
|
303
|
+
def self.lead_path_chopped long_path, lead_path
|
304
|
+
|
305
|
+
return long_path.gsub(lead_path, "")[1..-1]
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
# -- ------------------------------------------------------------------- -- #
|
311
|
+
# -- Returns true when the parameter file contains the parameter string. -- #
|
312
|
+
# -- As a side effect the lines with at least 1 string match are logged. -- #
|
313
|
+
# -- ------------------------------------------------------------------- -- #
|
314
|
+
def self.has_string? the_file, theString
|
315
|
+
|
316
|
+
containsMatch = false;
|
317
|
+
line_index = 0;
|
318
|
+
|
319
|
+
File.open( the_file, "r") do | file_obj |
|
320
|
+
|
321
|
+
name_abbrv = File.basename the_file
|
322
|
+
file_obj.each_line do | file_line |
|
323
|
+
|
324
|
+
line_index = line_index + 1
|
325
|
+
lineCount = sprintf '%03d', line_index
|
326
|
+
if file_line.include? theString then
|
327
|
+
|
328
|
+
squeezed_line = file_line.chomp.strip.squeeze(" ")
|
329
|
+
log.info(ere) { "== string [#{theString}] occurs @line #{lineCount} in #{name_abbrv}" }
|
330
|
+
log.info(ere) { "== |---> #{squeezed_line}" }
|
331
|
+
containsMatch = true
|
332
|
+
|
333
|
+
end
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
|
339
|
+
return containsMatch;
|
340
|
+
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
# --
|
345
|
+
# -- [FIND] lines that include a set of configured strings and
|
346
|
+
# -- [REPLACE] then with the configured alternative.
|
347
|
+
# --
|
348
|
+
# -- -----------
|
349
|
+
# -- Parameters
|
350
|
+
# -- -----------
|
351
|
+
# --
|
352
|
+
# -- filepath : path to existing "to be changed" file
|
353
|
+
# -- includes : include string array for line matching
|
354
|
+
# -- new_line : replace the matched line with this str
|
355
|
+
# --
|
356
|
+
# -- --------------------------------
|
357
|
+
# -- Dependencies and Assumptions
|
358
|
+
# -- --------------------------------
|
359
|
+
# --
|
360
|
+
# -- file exists at filepath
|
361
|
+
# --
|
362
|
+
def self.find_replace_lines filepath, includes, new_line
|
363
|
+
|
364
|
+
Throw.if_not_exists filepath
|
365
|
+
Throw.if_nil includes
|
366
|
+
Throw.if_nil new_line
|
367
|
+
|
368
|
+
line_matches_count = 0;
|
369
|
+
new_file_lines_set = ""
|
370
|
+
|
371
|
+
File.open( filepath, "r") do | file_obj |
|
372
|
+
|
373
|
+
file_obj.each_line do | file_line |
|
374
|
+
|
375
|
+
unless (String.includes_all?( file_line, includes ) ) then
|
376
|
+
new_file_lines_set += file_line
|
377
|
+
next
|
378
|
+
end
|
379
|
+
|
380
|
+
++line_matches_count
|
381
|
+
new_file_lines_set += new_line
|
382
|
+
|
383
|
+
log.info(ere) { "[replace] - ------------------------------------------------------- ##" }
|
384
|
+
log.info(ere) { "[replace] - file name => #{File.basename filepath}" }
|
385
|
+
log.info(ere) { "[replace] - has words => #{pp includes}" }
|
386
|
+
log.info(ere) { "[replace] - orig line => #{file_line}" }
|
387
|
+
log.info(ere) { "[replace] - ------- --------- ------- ---------- ------ ##" }
|
388
|
+
log.info(ere) { "[replace] - outgoing line => #{file_line}" }
|
389
|
+
log.info(ere) { "[replace] - incoming line => #{new_line}" }
|
390
|
+
log.info(ere) { "[replace] - ------- --------- ------- ---------- ------ ##" }
|
391
|
+
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
# -- ---------------------------------------------------------- -- #
|
397
|
+
# -- [(over)write] new set of file lines to the parameter file. -- #
|
398
|
+
# -- ---------------------------------------------------------- -- #
|
399
|
+
File.write filepath, new_file_lines_set
|
400
|
+
LogObject.file filepath, "replace"
|
401
|
+
|
402
|
+
end
|
403
|
+
|
404
|
+
|
405
|
+
# --
|
406
|
+
# -- Write the 1D key/value map into a properties
|
407
|
+
# -- file at the parameter folder.
|
408
|
+
# --
|
409
|
+
# -- Parameters
|
410
|
+
# -- properties_map : the key/value map to serialize
|
411
|
+
# -- props_dir_path : folder holding new properties file
|
412
|
+
# -- props_filename : name of the new properties file
|
413
|
+
# --
|
414
|
+
# -- Dependencies and Assumptions
|
415
|
+
# -- the directory will be created if it does not exist
|
416
|
+
# -- we assume the properties file DOES NOT EXIST
|
417
|
+
# -- the map is 1D and is not nil (can be empty)
|
418
|
+
# -- the directory is writeable by the user
|
419
|
+
# --
|
420
|
+
def self.write_properties properties_map, props_dir_path, props_filename
|
421
|
+
|
422
|
+
Dir.mkdir props_dir_path unless File.exists? props_dir_path
|
423
|
+
prop_filepath = File.join props_dir_path, props_filename
|
424
|
+
File.write prop_filepath, to_properties_text(properties_map)
|
425
|
+
|
426
|
+
LogObject.file prop_filepath, "write properties"
|
427
|
+
|
428
|
+
end
|
429
|
+
|
430
|
+
|
431
|
+
# --
|
432
|
+
# -- Create txt file in the properties format containing
|
433
|
+
# -- a dictionary of name/value pairs separated by an
|
434
|
+
# -- equals sign.
|
435
|
+
# --
|
436
|
+
# -- Parameters
|
437
|
+
# -- properties_map : the key/value map to serialize
|
438
|
+
# --
|
439
|
+
# -- Dependencies and Assumptions
|
440
|
+
# -- the map is 1D and is not nil (can be empty)
|
441
|
+
# -- map keys are SYMBOLS so underscores are made dots
|
442
|
+
# --
|
443
|
+
def self.to_properties_text properties_map
|
444
|
+
|
445
|
+
hdr_1 = "## Properties file with [#{properties_map.length}] key/value pairs.\n"
|
446
|
+
hdr_u = "## @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ##\n"
|
447
|
+
|
448
|
+
property_text = hdr_u + hdr_1 + hdr_u + "\n"
|
449
|
+
properties_map.each do |key_symbol,value|
|
450
|
+
key_string = key_symbol.to_s.gsub("_", ".")
|
451
|
+
property_text += "#{key_string}=#{value}\n"
|
452
|
+
end
|
453
|
+
|
454
|
+
property_text += "\n" + hdr_u
|
455
|
+
return property_text
|
456
|
+
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
# -- ---------------------------------------------------------- -- #
|
461
|
+
# -- When the [file fact] replace [behaviour] is called against -- #
|
462
|
+
# -- a "file" it [replaces all occurrences] (as best it can) of -- #
|
463
|
+
# -- the given string within the file. Call replace occurrences -- #
|
464
|
+
# -- against a folder and it replaces in all constituent files. -- #
|
465
|
+
# -- ---------------------------------------------------------- -- #
|
466
|
+
# -- Be careful = this implementation is not that clever. So if -- #
|
467
|
+
# -- we try to replace all "Betty" occurrences - lines that may -- #
|
468
|
+
# -- contain ["BetBettyty"] will likely end up with a ["Betty"] -- #
|
469
|
+
# -- ---------------------------------------------------------- -- #
|
470
|
+
def self.factorize from_string, to_string, in_file
|
471
|
+
|
472
|
+
the_filename = File.basename in_file
|
473
|
+
|
474
|
+
log.info(ere) { "From String => #{from_string}" }
|
475
|
+
log.info(ere) { "[To] String => #{to_string}" }
|
476
|
+
log.info(ere) { "File [Name] => #{the_filename}" }
|
477
|
+
|
478
|
+
File.write( in_file, File.open( in_file, &:read ).gsub( from_string, to_string ) );
|
479
|
+
|
480
|
+
end
|
481
|
+
|
482
|
+
|
483
|
+
end
|