mkvtoolnix/rake.d/format_string_verifier.rb

83 lines
2.4 KiB
Ruby
Executable File

#!/usr/bin/env ruby
require 'digest/sha1'
class FormatStringVerifier
@@errors_to_ignore = {
"d2820b11" => true,
"f3230d7f" => true,
}
def read_entries file_name
entries = Array.new
flags = {}
IO.readlines(file_name).each_with_index do |line, line_number|
line.gsub! /[\r\n]/, ''
if /^msgid /.match line
entries << { :id => [ line ], :line_number => line_number + 1, :flags => flags }
flags = {}
elsif /^msgid_plural /.match line
entries[-1][:id] << line
elsif /^msgstr/.match line
entries[-1][:str] ||= Array.new
entries[-1][:str] << line
elsif /^"/.match line
entry = entries[-1]
str = entry[:str] ? entry[:str][-1] : entry[:id][-1]
str.gsub! /"$/, ''
str << line[1 .. line.length - 1]
elsif /^#,/.match line
flags = Hash[ *line.gsub(/^#,\s*/, '').split(/,\s*/).map { |flag| [ flag.to_sym, true ] }.flatten ]
end
end
entries
end
def verify file_name
matcher = /%(?:
%
| \|[0-9$a-zA-Z\.\-]+\|
| -?\.?\s?[0-9]*l?l?[a-zA-Z]
| [0-9]+%?
)/ix
errors = read_entries(file_name).select { |e| !e[:flags][:fuzzy] && !e[:id].nil? && (e[:id][0] != 'msgid ""') && !e[:str].nil? && e[:str].detect { |e| e != 'msgstr ""' } }.collect do |entry|
non_id = entry[:id][ 1 .. entry[:id].size - 1 ] + entry[:str]
formats = {
:id => entry[:id][0].scan(matcher).uniq.sort,
:non_id => non_id.collect { |e| e.scan(matcher) }.flatten.uniq.sort
}
missing = formats[:id] - formats[:non_id]
added = formats[:non_id] - formats[:id]
next nil if missing.empty? && added.empty?
digest = Digest::SHA1.new.update(([ file_name.gsub(/.*\//, ''), entry[:id][-1] ] + added + missing).join(':')).hexdigest[0..7]
next nil if @@errors_to_ignore[digest]
{ :line_number => entry[:line_number],
:added => added,
:missing => missing,
:digest => digest
}
end.compact
errors.each do |error|
messages = []
messages << ("- " + error[:missing].join(' ')) if !error[:missing].empty?
messages << ("+ " + error[:added ].join(' ')) if !error[:added ].empty?
puts "#{file_name}:#{error[:line_number]}: error: #{messages.join('; ')} (id: #{error[:digest]})"
end
return errors.empty?
end
end