# # File:: dlc_global_sig_checker.rb # Description:: Checks that DLC scripts only use certain global blocks. # Checks all .global_block.txt files against a text file of hashes for global blocks # If the text file specifies a hash value for a global block then all .global_block.txt files that list that global block must have that exact hash value # If the text file has a hash of 0 for a global block then the .global_block.txt files don't have to have a specific hash value. The hash should still be the same across all .global_block.txt files, # but that value doesn't have to match a value specified in the text file. # If the text file doesn't list a global block index then the .global_block.txt files can't contain that global block # Author:: Graeme Williamson - copied from Derek Ward's global_sig_checker.rb # Date:: 15 January 2014 # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'RSG.Base.Configuration.dll' require 'RSG.Base.dll' require 'System.Core' require 'mscorlib' require 'RSG.Pipeline.Core.dll' require 'RSG.Base.Windows.dll' include RSG::Base::Configuration include RSG::Base::Logging include RSG::Base::Logging::Universal include RSG::Base::OS include RSG::Base::Windows include RSG::Pipeline::Core require 'pipeline/os/options' include Pipeline require 'fileutils' #----------------------------------------------------------------------------- # Constants #----------------------------------------------------------------------------- AUTHOR = 'RSGEDI Tools' EMAIL = 'RSGEDI Tools <*tools@rockstarnorth.com>' OPTIONS = [ LongOption::new( 'source_folder', LongOption::ArgType.Required, 's', 'source_folder' ), LongOption::new( 'text_file', LongOption::ArgType.Required, 't', 'text_file' ), LongOption::new( 'wildcard', LongOption::ArgType.Required, 'w', 'wildcard' ), LongOption::new( 'email', LongOption::ArgType.Required, 'e', 'email' ), ] #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Entry-Point #----------------------------------------------------------------------------- if ( __FILE__ == $0 ) then puts "#{$0} #{$*}" hdr = "INFO_MSG: " g_Options = OS::Options::new( OPTIONS ) begin retcode = 0 if ( g_Options.is_enabled?( 'help' ) ) puts "#{__FILE__}" puts "Usage:" puts g_Options.usage() exit( 1 ) end LogFactory.CreateApplicationConsoleLogTarget( ) g_Log = LogFactory.CreateUniversalLog("dlc_global_sig_checker") g_LogFile = LogFactory.CreateUniversalLogFile("dlc_global_sig_checker", g_Log) # as UniversalLogFile g_Config = RSG::Base::Configuration::ConfigFactory::CreateConfig( ) source_folder = g_Options.get( 'source_folder' ) unless g_Options.get( 'source_folder' ).nil? text_file = g_Options.get( 'text_file' ) unless g_Options.get( 'text_file' ).nil? wildcard = g_Options.get( 'wildcard' ) unless g_Options.get( 'wildcard' ).nil? email = g_Options.get( 'email' ) unless g_Options.get( 'email' ).nil? g_Log.Message("#{hdr} ") g_Log.Message("#{hdr}************************") g_Log.Message("#{hdr}*** DlcGlobalSigChecker ***") g_Log.Message("#{hdr}************************") g_Log.Message("#{hdr} ") g_Log.Message("#{hdr}Source folder : #{source_folder}") g_Log.Message("#{hdr}Text file : #{text_file}") g_Log.Message("#{hdr}Wildcard : #{wildcard}"); g_Log.Message("#{hdr} ") if (!File.exist?(text_file)) g_Log.Warning("text file doesn't exist #{text_file}" ) exit ( 0 ) end regex = /^\s*(\d*)\s*=\s*(\d*)\s*$/i expected_block_hash = {} File.open(text_file) do |textfile| textfile.each_line do |line| # eg. # 0=2357115215,5=2198626599,10=0 entries = line.split(',') entries.each do |entry| if (entry=~regex) block_idx = $1 block_hash_value = $2 if expected_block_hash.key?(block_idx) g_Log.Error("#{hdr}\t\tText file #{text_file} contains more than one entry for global index #{block_idx}") else expected_block_hash[block_idx] = block_hash_value g_Log.Message("\tEstablished block hash \t#{block_idx} = #{block_hash_value}\t from text file #{text_file}") end else g_Log.Message("\t\t?Unexpected entry when reading from text file #{text_file} : #{entry}") end end end end if (!File.directory? source_folder) g_Log.Warning("directory doesnt exist #{source_folder}" ) exit ( 0 ) end files = System::IO::Directory.GetFiles(source_folder, wildcard) if (files == nil || files.Length==0) g_Log.Warning("no files found in #{source_folder}" ) exit ( 0 ) end num_files = files.size g_Log.Message("#{hdr}------ Checking #{num_files} files --------") inconsistencies = 0 files.each do |filename| short_filename = File.basename(filename) File.open(filename) do |file| file.each_line do |line| # eg. # x:\Barry1,0=4260798006,1=3808128351,3=3921368841,4=3624207664,5=340217310,6=1588498831,8=2978757849,9=3874559245 entries = line.split(',') line_filename = entries.shift entries.each do |entry| if (entry=~regex) block_idx = $1 block_hash_value = $2 if expected_block_hash.key?(block_idx) expected_value = expected_block_hash[block_idx] if (expected_value != "0") && (expected_value != block_hash_value) g_Log.Error("#{hdr}\t\t Hash #{block_hash_value} for global block #{block_idx} in #{short_filename}(#{line_filename}) doesn't match with the expected value #{expected_value} in #{text_file}") inconsistencies += 1 end else g_Log.Error("#{hdr}\t\t #{short_filename}(#{line_filename}) can't use variables in global block #{block_idx}. That block is not listed in #{text_file}") inconsistencies += 1 end else g_Log.Message("\t\t?Unexpected entry : #{entry} when reading from #{short_filename}(#{line_filename})") end end end end end g_Log.Message("#{hdr}-------------------------------") g_Log.Message("#{hdr} ") g_Log.Message("#{hdr}---------- Summary ------------") g_Log.Message("#{hdr}Checked files : #{num_files}") g_Log.Message("#{hdr}Inconsistencies : #{inconsistencies}") g_Log.Message("#{hdr}-------------------------------") g_Log.Message("#{hdr} ") retcode = -1 if (inconsistencies>0) if (email=="true" && retcode == -1) g_Log.Error("Flushing logfile with error, retcode is #{retcode}") subject = "DLC Global Sig Differences detected in #{source_folder}\\#{wildcard}" body = "See attached log file" recipients = [] #recipients << "graeme.williamson@rockstarnorth.com" #recipients << "ben.rollinson@rockstarnorth.com" recipients << "derek.ward@rockstarnorth.com" recipients << "liam.anderson@rockstarnorth.com" g_Log.Message("Sending Email : {0} : {1}", subject, recipients.join(",")) recipients = recipients.to_clr( System::String ) attachments = [System::Net::Mail::Attachment.new(g_LogFile.Filename)] attachments = attachments.to_clr( System::Net::Mail::Attachment ) RSG::Base::Configuration::Email::Email.SendEmail(g_Config, recipients, subject, body, attachments) end g_Log.Message("#{hdr}dlc_global_sig_checker exiting with #{retcode}") exit retcode rescue SystemExit => sex LogFactory.ApplicationShutdown() exit( sex.status ) rescue Exception => ex g_Log.Exception( ex, "Exception during #{__FILE__}." ) puts "Exception during #{__FILE__}: #{ex.message}" puts ex.backtrace.join("\n") if ( g_Options.show_popups? ) then dlg = RSG::Base::Windows::ExceptionStackTraceDlg::new( ex, g_Config.EmailAddress, AUTHOR, EMAIL ) dlg.ShowDialog( ) end exit( -1 ) end end # dlc_global_sig_checker.rb