mkvtoolnix/rake.d/format_string_verifier.rb
Moritz Bunkus d6707da459
build system: protect digest calls from re-entry
The code for Ruby's Digest module seems to be racy
wrt. multi-threading. See e.g.
https://github.com/aws/aws-sdk-ruby/issues/525 for details.
2018-12-04 21:13:17 +01:00

65 lines
1.9 KiB
Ruby
Executable File

#!/usr/bin/env ruby
class FormatStringVerifier
def verify file_name
language = file_name.gsub(%r{.*/|\.po$}, '')
to_ignore = {
'eu' => [ '74f8165349457fb0d89a559ffa83c4b3b3c1993b', 'aa8f04e33094d67c75256a298364323f38967abf' ],
'tr' => [ '62fc63d5ae795e24fcdbdfd5ec300c7bf5e46b76' ],
}
entries = read_po(file_name).
reject { |e| e[:obsolete] }.
select { |e| e[:msgid] && e[:msgstr] && e[:flags] }.
reject { |e| e[:msgid].empty? || e[:msgstr].empty? }.
reject { |e| e[:msgstr].all?(&:empty?) }.
reject { |e| e[:flags].include?("fuzzy") }
errors = []
matchers = {
:fmt => /( \{ \d+ (?: : [^\}]+ )? \} )/ix,
:qt => /( (?<! %) % \d+ (?! [a-z]) )/ix,
}
format_types = matchers.keys
entries.each do |e|
formats = Hash[ *matchers.keys.map { |key| [ key, { :id => [], :str => [] } ] }.flatten ]
error_digests = []
e[:msgstr].each_with_index do |msgstr, idx|
( (e[:msgid] || []) + (e[:msgid_plural] || []) ).
reject(&:nil?).
each do |msgid|
format_types.each do |type|
sha1 = sha1_hexdigest "#{type}:#{msgid}:#{msgstr}"
next if to_ignore.key?(language) && to_ignore[language].include?(sha1)
store = formats[type]
store[:id] << msgid .scan(matchers[type]).uniq.sort
store[:str] << msgstr.scan(matchers[type]).uniq.sort
missing = store[:id] - store[:str]
added = store[:str] - store[:id]
error_digests << sha1 if !missing.empty? || !added.empty?
end
end
end
errors << { :line => e[:line], :digests => error_digests } if !error_digests.empty?
end
# pp errors
errors.each do |error|
puts "#{file_name}:#{error[:line]}: error: format string differences (IDs: #{error[:digests].sort.join(' ')})"
end
return errors.empty?
end
end