-- gall.util
--
-- Git Abstraction Layer for Lua -- Utility functions
--
-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
--
--

local luxio = require 'luxio'
local sp = require 'luxio.subprocess'

local function deep_copy(t, memo)
   if not memo then memo = {} end
   if memo[t] then return memo[t] end
   local ret = {}
   memo[t] = ret
   local kk, vv
   for k, v in pairs(t) do
      kk, vv = k, v
      if type(k) == "table" then
	 kk = deep_copy(k, memo)
      end
      if type(v) == "table" then
	 vv = deep_copy(v, memo)
      end
      ret[kk] = vv
   end
   return ret
end

local function validate_signature(obj, keyring)
   local sig_pipe  = {}
   luxio.pipe(sig_pipe)
   local null = luxio.open("/dev/null", luxio.O_RDONLY)
   local proc = sp.spawn {
      "gpgv", "--keyring", keyring,
      "-q", "--status-fd", "1", "/proc/self/fd/" .. tostring(sig_pipe[1]),
      "-",
      stdin = sp.PIPE,
      stdout = sp.PIPE,
      stderr = null,
      close_in_child = {
	 sig_pipe[2], null
      }
   }
   luxio.close(sig_pipe[1])
   luxio.close(null)
   -- gpgv first reads the signature file
   luxio.write(sig_pipe[2], obj.signature) -- going to assume it got written
   luxio.close(sig_pipe[2])
   -- gpgv next reads the certificate (which is sat on its stdin pipe)
   luxio.write(proc.stdin, obj.signedcert)
   luxio.close(proc.stdin)
   -- Finally, we read the content of the stdout pipe
   local gpgv_output, l = {}
   repeat
      l = luxio.read(proc.stdout, 4096)
      if l then gpgv_output[#gpgv_output+1] = l end
   until (not l) or (l == "")
   gpgv_output = table.concat(gpgv_output, "")
   luxio.close(proc.stdout)
   local how, why = proc:wait()
   if how ~= "exit" then
      return nil, ("%s: %d"):format(how, why)
   end
   if why ~= 0 then
      return false, gpgv_output
   end
   -- We are looking for a line which is of the form:
   -- [GNUPG:] VALIDSIG 6CCCE5B17306BCDC179CF954C30DF439F2987D74 2016-08-28 1472393046 0 3 0 1 10 00 19568523759E2A2858F4606B3CCEBABE206C3B69
   local fprint = gpgv_output:match(" VALIDSIG ([0-9A-F]+) ")
   if not fprint then
      return false, gpgv_output
   end
   return fprint
end

return {
   deep_copy = deep_copy,
   validate_signature = validate_signature,
}
