# frozen_string_literal: true module RakeUi class RakeTaskLog < OpenStruct # year-month-day-hour(24hour time)-minute-second-utc ID_DATE_FORMAT = "%Y-%m-%d-%H-%M-%S%z" REPOSITORY_DIR = Rails.root.join("tmp", "rake_ui") FILE_DELIMITER = "____" FINISHED_STRING = "+++++ COMMAND FINISHED +++++" TASK_HEADER_OUTPUT_DELIMITER = "-------------------------------" FILE_ITEM_SEPARATOR = ": " def self.create_tmp_file_dir FileUtils.mkdir_p(REPOSITORY_DIR.to_s) end def self.truncate FileUtils.rm_rf(Dir.glob(REPOSITORY_DIR.to_s + "/*")) end def self.build_from_file(log_file_name) log_file_name.split(FILE_DELIMITER) new( id: log_file_name.gsub(".txt", ""), log_file_name: log_file_name, log_file_full_path: Rails.root.join(REPOSITORY_DIR, log_file_name).to_s ) end def self.build_new_for_command(name:, rake_definition_file:, rake_command:, raker_id:, args: nil, environment: nil) create_tmp_file_dir date = Time.now.strftime(ID_DATE_FORMAT) id = "#{date}#{FILE_DELIMITER}#{raker_id}" log_file_name = "#{id}.txt" log_file_full_path = REPOSITORY_DIR.join(log_file_name).to_s File.open(log_file_full_path, "w+") do |f| f.puts "id#{FILE_ITEM_SEPARATOR}#{id}" f.puts "name#{FILE_ITEM_SEPARATOR}#{name}" f.puts "date#{FILE_ITEM_SEPARATOR}#{date}" f.puts "args#{FILE_ITEM_SEPARATOR}#{args}" f.puts "environment#{FILE_ITEM_SEPARATOR}#{environment}" f.puts "rake_command#{FILE_ITEM_SEPARATOR}#{rake_command}" f.puts "rake_definition_file#{FILE_ITEM_SEPARATOR}#{rake_definition_file}" f.puts "log_file_name#{FILE_ITEM_SEPARATOR}#{log_file_name}" f.puts "log_file_full_path#{FILE_ITEM_SEPARATOR}#{log_file_full_path}" f.puts TASK_HEADER_OUTPUT_DELIMITER.to_s f.puts " INVOKED RAKE TASK OUTPUT BELOW" f.puts TASK_HEADER_OUTPUT_DELIMITER.to_s end new(id: id, name: name, args: args, environment: environment, rake_command: rake_command, rake_definition_file: rake_definition_file, log_file_name: log_file_name, log_file_full_path: log_file_full_path) end def self.all create_tmp_file_dir Dir.entries(REPOSITORY_DIR).reject { |file| file == "." || file == ".." }.map do |log| RakeUi::RakeTaskLog.build_from_file(log) end end def self.find_by_id(id) all.find do |a| a.id == id || a.id == RakeUi::RakeTask.to_safe_identifier(id) end end def self.for(rake_ui_rake_task) all.select do |history| history.id == rake_ui_rake_task.id end end def name super || parsed_log_file_name[:name] || parsed_file_contents[:name] end def date super || parsed_log_file_name[:date] || parsed_file_contents[:date] end def args super || parsed_file_contents[:args] end def environment super || parsed_file_contents[:environment] end def rake_command super || parsed_file_contents[:rake_command] end def rake_definition_file super || parsed_file_contents[:rake_definition_file] end def log_file_name super || parsed_file_contents[:log_file_name] end def log_file_full_path super || parsed_file_contents[:log_file_full_path] end def rake_command_with_logging "#{rake_command} 2>&1 >> #{log_file_full_path}" end def file_contents @file_contents ||= File.read(log_file_full_path) end def command_to_mark_log_finished "echo #{FINISHED_STRING} >> #{log_file_full_path}" end def finished? file_contents.include? FINISHED_STRING end private # converts standard formatted file id into an object def parsed_log_file_name @parsed_log_file_name ||= {}.tap do |parsed| date, name = id.split(FILE_DELIMITER, 2) parsed[:date] = date parsed[:name] = RakeUi::RakeTask.from_safe_identifier(name) end end # converts our persisted rake logs files into an object # name: foo # id: baz # # into # # { name: 'foo', id: 'baz' } def parsed_file_contents return @parsed_file_contents if defined? @parsed_file_contents @parsed_file_contents = {}.tap do |parsed| File.foreach(log_file_full_path).first(9).each do |line| name, value = line.split(FILE_ITEM_SEPARATOR, 2) next unless name parsed[name] = value && value.delete("\n") end end.with_indifferent_access end end end