Class: Files

Inherits:
Object
  • Object
show all
Defined in:
lib/opensecret/plugins.io/file/file.rb

Overview

– ————————————————————— – # – File facts are placeholders (keys in effect) just begging to be – # – replaced by values sourced from some sort of map. This software – # – centres around the DevOps fact replacement placeholder pattern. – # – ————————————————————— – #

Class Method Summary collapse

Class Method Details

.factorize(from_string, to_string, in_file) ⇒ Object

– ———————————————————- – # – When the [file fact] replace [behaviour] is called against – # – a “file” it [replaces all occurrences] (as best it can) of – # – the given string within the file. Call replace occurrences – # – against a folder and it replaces in all constituent files. – # – ———————————————————- – # – Be careful = this implementation is not that clever. So if – # – we try to replace all “Betty” occurrences - lines that may – # – contain [“BetBettyty”] will likely end up with a [“Betty”] – # – ———————————————————- – #



470
471
472
473
474
475
476
477
478
479
480
# File 'lib/opensecret/plugins.io/file/file.rb', line 470

def self.factorize from_string, to_string, in_file

  the_filename = File.basename in_file

  log.info(ere) { "From String => #{from_string}" }
  log.info(ere) { "[To] String => #{to_string}" }
  log.info(ere) { "File [Name] => #{the_filename}" }

  File.write( in_file, File.open( in_file, &:read ).gsub( from_string, to_string ) );

end

.find_replace(fact_map, replace_folder) ⇒ Object

– – Scan every file in directory for placeholder keys within the – parameter map and replace them with the corresponding value. – Not Recursive => the scan does [not] recurse into folders – – ———————————- – Replacing Betty (Nested Replace) – ———————————- – – “GoBBetBettytyettyne” => “Gone” – – A nested replace is done up to approximately 5 levels deep. – So replacing “Betty” from the above string does [NOT] produce – “GoBBettyettyne”. The string becomes “Gone”. – – ———– – Parameters – ———– – fact_map : driving [placeholder] => [value] map – replace_dir : dir subject of the scan and replace –



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/opensecret/plugins.io/file/file.rb', line 55

def self.find_replace fact_map, replace_folder

  log.info(ere){ "#-- --------------------------------------------------------- #" }
  log.info(ere){ "#-- File changing in #{File.basename replace_folder}" }
  log.info(ere){ "#-- #{replace_folder}" }
  log.info(ere){ "#-- --------------------------------------------------------- #" }

  # -- ------------------------------------------------------------------------------ -- #
  # -- Iterate to substitute matched strings in file with their corresponding values. -- #
  # -- ------------------------------------------------------------------------------ -- #
  Dir.foreach( replace_folder ) do | file_name |

    file_path = File.join replace_folder, file_name
    next if File.directory? file_path
    next if File.extname(file_path).eql? ".log"

    nested_key_replace fact_map, file_path

  end

  log.info(ere){ "#-- --------------------------------------------------------- #" }
  log.info(ere){ "#-- Done changing files in #{File.basename replace_folder}" }
  log.info(ere){ "#-- --------------------------------------------------------- #" }
  
end

.find_replace_lines(filepath, includes, new_line) ⇒ Object

– – [FIND] lines that include a set of configured strings and – [REPLACE] then with the configured alternative. – – ———– – Parameters – ———– – – filepath : path to existing “to be changed” file – includes : include string array for line matching – new_line : replace the matched line with this str – – ——————————– – Dependencies and Assumptions – ——————————– – – file exists at filepath –



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/opensecret/plugins.io/file/file.rb', line 362

def self.find_replace_lines filepath, includes, new_line

  Throw.if_not_exists filepath
  Throw.if_nil includes
  Throw.if_nil new_line

  line_matches_count = 0;
  new_file_lines_set = ""

  File.open( filepath, "r") do | file_obj |

    file_obj.each_line do | file_line |

      unless (String.includes_all?( file_line, includes ) ) then
        new_file_lines_set += file_line
        next
      end

      ++line_matches_count
      new_file_lines_set += new_line

      log.info(ere) { "[replace] - ------------------------------------------------------- ##" }
      log.info(ere) { "[replace] - file name => #{File.basename filepath}" }
      log.info(ere) { "[replace] - has words => #{pp includes}" }
      log.info(ere) { "[replace] - orig line => #{file_line}" }
      log.info(ere) { "[replace] - -------   ---------    -------    ----------   ------   ##" }
      log.info(ere) { "[replace] - outgoing line => #{file_line}" }
      log.info(ere) { "[replace] - incoming line => #{new_line}" }
      log.info(ere) { "[replace] - -------   ---------    -------    ----------   ------   ##" }

    end
    
  end

  # -- ---------------------------------------------------------- -- #
  # -- [(over)write] new set of file lines to the parameter file. -- #
  # -- ---------------------------------------------------------- -- #
  File.write filepath, new_file_lines_set
  LogObject.file filepath, "replace"

end

.forwarded_path(files_map) ⇒ Object

– – Return a new map with the values folder path – forwarded by one level – – If the map contains the below – – { – file1 => user/docs/pdfs, – file2 => user/docs/pdfs/good, – file3 => user/docs/pdfs/bad – } – – This method will return a map like this – – { – file1 => docs/pdfs, – file2 => docs/pdfs/good, – file3 => docs/pdfs/bad – } – – The values part has been forwarded by one level. –



266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/opensecret/plugins.io/file/file.rb', line 266

def self.forwarded_path files_map

  changed_map = {}

  files_map.each do |the_name, the_old_path|
    the_new_path = the_old_path.split("/")[1..-1].join("/")
    changed_map.store the_name, the_new_path
    log.info(ere){ "Forwarded from #{the_old_path} to #{the_new_path}" }
  end

  return changed_map

end

.has_string?(the_file, theString) ⇒ Boolean

– ——————————————————————- – # – Returns true when the parameter file contains the parameter string. – # – As a side effect the lines with at least 1 string match are logged. – # – ——————————————————————- – #

Returns:

  • (Boolean)


314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/opensecret/plugins.io/file/file.rb', line 314

def self.has_string? the_file, theString

  containsMatch = false;
  line_index = 0;

  File.open( the_file, "r") do | file_obj |

    name_abbrv = File.basename the_file
    file_obj.each_line do | file_line |

      line_index = line_index + 1
      lineCount = sprintf '%03d', line_index
      if file_line.include? theString then

        squeezed_line = file_line.chomp.strip.squeeze(" ")
        log.info(ere) { "== string [#{theString}] occurs @line #{lineCount} in #{name_abbrv}" }
        log.info(ere) { "==  |---> #{squeezed_line}" }
        containsMatch = true

      end

    end
    
  end

  return containsMatch;

end

.in_folders(parent_folders) ⇒ Object

– – Produce a map of every “recursive” file sitting under – any and all of the parameter directories array. – – Harboured folders are traversed but folder names are – excluded from the resulting map. – – The key/value structure of the map is – – key => simple filename – value => (abs) folder path – – ——————————– – Filename NOT UNIQUE Exception – ——————————– – – Simple filename UNIQUENESS must prevail. – – If the same base filename is found in any part or level – of the directory trees under the every parameter parent – folder - an exception will be thrown. –



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/opensecret/plugins.io/file/file.rb', line 157

def self.in_folders parent_folders

  files_map = {}

  parent_folders.each do |parent_folder|

    log.info(ere) { "Create map of files under #{nickname parent_folder}" }
    Throw.if_not_exists parent_folder

    Dir["#{parent_folder}/**/*"].each do |child_file|

      next if File.directory? child_file
      filename = File.basename child_file
      foldername = File.dirname child_file
      log.info(ere) { " #{filename} => #{nickname foldername}" }
      error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
      raise RuntimeError.new error_str if files_map.has_key? filename
      files_map.store filename, foldername

    end

  end

  return files_map

end

.key_replace(source_map, filepath) ⇒ Object

– – Using the parameter [file] [replace] any occurence – of any [key] found in the parameter [map] with the – corresponding mapped key [value]. – – Side Effect => If at least one replacement occured this – method returns true, else false. –



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/opensecret/plugins.io/file/file.rb', line 117

def self.key_replace source_map,  filepath

    replace_happened = false

    source_map.each do |theKey, theValue|

      next unless has_string? filepath, theKey
      factorize theKey, theValue, filepath
      replace_happened = true

    end

    return replace_happened

end

.lead_path_chopped(long_path, lead_path) ⇒ Object

– – Path stripper expects the path in the first parameter – to start with the path in the second parameter. – – It then returns the first parameter path with the – leading path stripped out. – – ————————— – Strip Leading Path Example – ————————— – – 1st param path = /home/joe/docs/pdfs/websites – 2nd param path = /home/joe/docs – Returned Path = pdfs/websites – – ——————————— – The Middle Separator is Stripped – ——————————— – – Note above that the middle separator is stripped – so the returned string has no leading separator. –



303
304
305
306
307
# File 'lib/opensecret/plugins.io/file/file.rb', line 303

def self.lead_path_chopped long_path, lead_path

  return long_path.gsub(lead_path, "")[1..-1]

end

.nested_key_replace(source_map, filepath) ⇒ Object

– – Using the parameter [file] [replace] any occurence – of any [key] found in the parameter [map] with the – corresponding mapped key [value]. – – ———————————– – [Nested Replace] – Replacing Betty (Nested Replace) – ———————————- – – “GoBBetBettytyettyne” => “Gone” – – A nested replace is done up to approximately 5 levels deep. – So replacing “Betty” from the above string does [NOT] produce – “GoBBettyettyne”. The string becomes “Gone”. –



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/opensecret/plugins.io/file/file.rb', line 97

def self.nested_key_replace source_map,  filepath

  for i in 1..5
    file_changed = key_replace source_map, filepath
    return unless file_changed
    log.info(ere){ "#-- --------------------------------------------------------- #" }
    log.info(ere){ "#-- File #{File.basename filepath} has been changed" }
    log.info(ere){ "#-- --------------------------------------------------------- #" }
  end

end

.to_name_path_map(base_folder, file_extn) ⇒ Object

– – Find files of a given type (extension) that exist – recursively under a folder. – – ——————————– – Filename NOT UNIQUE Exception – ——————————– – – Simple filename UNIQUENESS must prevail. – – If the same base filename is found in any part or level – of the directory trees under the every parameter parent – folder - an exception will be thrown. – – ———— – Parameters – ———— – – base_folder => the top-level folder to search – dir at (abs) path must exist – – file_extn => extension of interesting files – including the leading [period]. – (send “.exe” for exe files) – (send “.md” for markdown files) – – ———— – Map Returned – ———— – – Returns a { filename => rel_path } map of the matching – files in the folder. The map – – keys => simple filename without extension – values => relative path from the base folder –



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/opensecret/plugins.io/file/file.rb', line 221

def self.to_name_path_map base_folder, file_extn

  files_map = {}

  Dir["#{base_folder}/**/*#{file_extn}"].each do |filepath|

    next if File.directory? filepath
    ext_error = "File extension not [#{file_extn}] in => #{nickname filepath}"
    raise RuntimeError.new(ext_error) unless File.extname(filepath).eql? "#{file_extn}"

    filename = File.basename filepath

    error_str = "Name NOT UNIQUE Error => [#{filename}].\n\n#{files_map.inspect}"
    raise RuntimeError.new error_str if files_map.has_key? filename
    files_map.store filename, filepath

  end

  return files_map

end

.to_properties_text(properties_map) ⇒ Object

– – Create txt file in the properties format containing – a dictionary of name/value pairs separated by an – equals sign. – – Parameters – properties_map : the key/value map to serialize – – Dependencies and Assumptions – the map is 1D and is not nil (can be empty) – map keys are SYMBOLS so underscores are made dots –



443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# File 'lib/opensecret/plugins.io/file/file.rb', line 443

def self.to_properties_text properties_map

  hdr_1 = "## Properties file with [#{properties_map.length}] key/value pairs.\n"
  hdr_u = "## @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ##\n"

  property_text = hdr_u + hdr_1 + hdr_u + "\n"
  properties_map.each do |key_symbol,value|
    key_string = key_symbol.to_s.gsub("_", ".")
    property_text += "#{key_string}=#{value}\n"
  end

  property_text += "\n" + hdr_u
  return property_text

end

.write_properties(properties_map, props_dir_path, props_filename) ⇒ Object

– – Write the 1D key/value map into a properties – file at the parameter folder. – – Parameters – properties_map : the key/value map to serialize – props_dir_path : folder holding new properties file – props_filename : name of the new properties file – – Dependencies and Assumptions – the directory will be created if it does not exist – we assume the properties file DOES NOT EXIST – the map is 1D and is not nil (can be empty) – the directory is writeable by the user –



420
421
422
423
424
425
426
427
428
# File 'lib/opensecret/plugins.io/file/file.rb', line 420

def self.write_properties properties_map, props_dir_path, props_filename

  Dir.mkdir props_dir_path unless File.exists? props_dir_path
  prop_filepath = File.join props_dir_path, props_filename
  File.write prop_filepath, to_properties_text(properties_map)

  LogObject.file prop_filepath, "write properties"

end