#!/usr/bin/env ruby ## tip: to test run: ## ruby -I ./lib bin/fbchk ## our own code require 'sportdb/formats' require 'optparse' ## local hack ## if exists up-to-date catalog db (use local version NOT built-in) catalog_path = '../catalog/catalog.db' if File.exist?( catalog_path ) SportDb::Import.config.catalog_path = catalog_path end args = ARGV opts = { debug: false, file: nil, teams: true, ## check/lint teams (name errros etc.) } parser = OptionParser.new do |parser| parser.banner = "Usage: #{$PROGRAM_NAME} [options]" ## ## check if git has a offline option?? (use same) ## check for other tools - why? why not? # parser.on( "-q", "--quiet", # "less debug output/messages - default is (#{!opts[:debug]})" ) do |debug| # opts[:debug] = false # end parser.on( "--verbose", "--debug", "turn on verbose / debug output (default: #{opts[:debug]})" ) do |debug| opts[:debug] = true end parser.on( "-f FILE", "--file FILE", "read datafiles (pathspecs) via .csv file") do |file| opts[:file] = file end parser.on( "--[no]-teams", "turn on/off team name checks (default: #{opts[:teams]})") do |teams| opts[:teams] = teams end end parser.parse!( args ) puts "OPTS:" p opts puts "ARGV:" p args ## todo/check - use packs or projects or such ## instead of specs - why? why not? specs = [] if opts[:file] recs = read_csv( opts[:file] ) pp recs ## note - make pathspecs relative to passed in file arg!!! basedir = File.dirname( opts[:file] ) recs.each do |rec| paths = SportDb::Parser::Opts.find( rec['path'], dir: basedir ) specs << [paths, rec] end else paths = if args.empty? [] else ## check for directories ## and auto-expand SportDb::Parser::Opts.expand_args( args ) end specs << [paths, {}] end if opts[:debug] SportDb::QuickMatchLinter.debug = true SportDb::QuickMatchReader.debug = true SportDb::MatchParser.debug = true else SportDb::QuickMatchLinter.debug = false SportDb::QuickMatchReader.debug = false SportDb::MatchParser.debug = false LogUtils::Logger.root.level = :info end specs.each_with_index do |(paths, rec),i| errors = [] paths.each_with_index do |path,j| puts "==> [#{j+1}/#{paths.size}] reading >#{path}<..." quick = SportDb::QuickMatchLinter.new( read_text( path ), check_teams: opts[:teams] ) matches = quick.parse if quick.errors? puts "!! #{quick.errors.size} error(s):" pp quick.errors quick.errors.each do |err| errors << [ path, *err ] # note: use splat (*) to add extra values (starting with msg) end end puts " #{matches.size} match(es)" end if errors.size > 0 puts puts "!! #{errors.size} PARSE ERRORS in #{paths.size} datafile(s)" pp errors else puts puts " OK - no parse errors in #{paths.size} datafile(s)" end ## add errors to rec via rec['errors'] to allow ## for further processing/reporting rec['errors'] = errors end ### ## generate a report if --file option used if opts[:file] buf = String.new buf << "# fbchk summary report - #{specs.size} dataset(s)\n\n" specs.each_with_index do |(paths, rec),i| errors = rec['errors'] if errors.size > 0 buf << "!! #{errors.size} ERROR(S) " else buf << " OK " end buf << "%-20s" % rec['path'] buf << " - #{paths.size} datafile(s)" buf << "\n" if errors.size > 0 buf << errors.pretty_inspect buf << "\n" end end puts puts "SUMMARY:" puts buf basedir = File.dirname( opts[:file] ) basename = File.basename( opts[:file], File.extname( opts[:file] )) outpath = "#{basedir}/fbcheck.#{basename}.txt" write_text( outpath, buf ) end puts "bye"