#!/usr/bin/env lua5.1-courseware

require 'osutil'

local posix = require 'courseware-posix'

local stringf = string.format
local function runf(...) return os.execute(string.format(...)) end
local function eprintf(...) return io.stderr:write(string.format(...)) end

local backends = { 'toascii', 'toroff', 'unmarkup', 'nt', 'tohtml', 'totex' }

local filters = { 'noidx' }

local fields = (require 'flags').parser()
  :string('old', '/usr/lib/noweb'):help('installation directory of old version')
  :numarg(1)
  :parse(arg)

local newdir = assert(arg[1])

local function outfiles(command)
  local tmp = os.capture 'mktemp --tmpdir nwregression.XXXXXX'
  local tmp2 = os.capture 'mktemp --tmpdir nwregression.XXXXXX'
  runf('%s > %s 2> %s', command, tmp, tmp2)
  return tmp, tmp2
end

local options = { nt = '-R*' }

local pipelines = { }
do
  local function extend(c, i)
    local n = i == nil and #pipelines or i < 0 and #pipelines + 1 + i or i
    assert(pipelines[n])
    local next = stringf('%s | %s', pipelines[n], stringf('$L/%s %s', c, options[c] or ''))
    table.insert(pipelines, next)
  end

  table.insert(pipelines, '$L/markup %s')
  for _, f in ipairs(filters) do
    if posix.access(stringf('%s/%s', newdir, f)) then
      extend(f)
    end
  end
  for i = 1, #pipelines do
    for _, b in ipairs(backends) do
      extend(b, i)
    end
  end
end
  
local sources = os.capture('echo $HOME/noweb/dist/src/c/*.nw')

local warned = { }

local function warn(s)
  if not warned[s] then
    warned[s] = true
    io.stderr:write(s, '\n')
  end
end

local function diffs_ok(cmd)
  if cmd:find '%Wnoidx%W.*%Wtotex%W' then
    warn 'totex known to be incompatible when used with toidx'
    return true
  elseif cmd:find '%Wtotex%W' then
    warn 'totex known to be incompatible even when used alone'
    return true
  elseif cmd:find '%Wnoidx%W.*%Wtohtml%W' then
    warn 'tohtml known to be incompatible when used with toidx'
    return true
  end
end

for _, p in ipairs(pipelines) do
  eprintf('%s\n', p)
  for f in sources:gmatch '%S+' do
    local oldc = stringf(p:gsub('%$L', fields.old), f)
    local newc = stringf(p:gsub('%$L', newdir),     f)
    local oldout, o2 = outfiles(oldc)
    local newout, n2 = outfiles(newc)

    local rc  = runf('cmp -s %s %s', oldout, newout)
    local rc2 = runf('cmp -s %s %s', o2, n2)
    if rc2 ~= 0 then
      eprintf('FAILED: %s\n        %s\n', oldc, newc)
      runf('colordiff -u %s %s | head -40', o2, n2)
      os.exit(1)
    elseif rc ~= 0 and not diffs_ok(newc) then
      runf('colordiff -u %s %s | head -40', oldout, newout)
      os.exit(1)
    else
      os.remove(oldout)
      os.remove(newout)
      os.remove(o2)
      os.remove(n2)
    end
  end
end
