-- test/test-gall.repository.lua
--
-- Git Abstraction layer for Lua - Repository tests
--
-- Copyright 2012 Daniel Silverstone <dsilvers@digital-scurf.org>
--
-- For Licence terms, see COPYING
--

-- This test includes repository wibbling
dofile "test/withrepo.lua"

-- Step one, start coverage

pcall(require, 'luacov')

local gall = require 'gall'

local testnames = {}

local real_assert = assert
local total_asserts = 0
local function assert(...)
   local retval = real_assert(...)
   total_asserts = total_asserts + 1
   return retval
end

local function add_test(suite, name, value)
   rawset(suite, name, value)
   testnames[#testnames+1] = name
end

local suite = setmetatable({}, {__newindex = add_test})

function suite.find_current_dot_git()
   os.execute("sh test/create_test_repo.sh")
   assert(gall.repository.new("test/test_repo/.git"))
end

function suite.find_current()
   os.execute("sh test/create_test_repo.sh")
   assert(gall.repository.new("test/test_repo"))
end

function suite.fail_to_find()
   local ok, msg = gall.repository.new("/DOES_NOT_EXIST")
   assert(not ok)
   assert(msg:find("DOES_NOT_EXIST"))
end

function suite.make_repo()
   assert(gall.repository.create("test/test_repo"))
end

function suite.make_repo_full()
   assert(gall.repository.create("test/test_repo", true))
end

function suite.make_fail()
   local ok, msg = gall.repository.create("/dev/null/CANNOT_CREATE")
   assert(not ok)
   assert(msg:find("CANNOT_CREATE"))
end

function suite.repo_tostring()
   os.execute("sh test/create_test_repo.sh")
   local repo = assert(gall.repository.new("test/test_repo"))
   local repstr = tostring(repo)
   assert(repstr:find("GitRepository"))
   assert(repstr:find("test/test_repo/%.git"))
end

function suite.repo_hash_blob()
   local repo = assert(gall.repository.create("test/test_repo"))
   local sha = repo:hash_object("blob", "FOOBAR")
   assert(sha == "389865bb681b358c9b102d79abd8d5f941e96551")
end

function suite.repo_create_blob()
   local repo = assert(gall.repository.create("test/test_repo"))
   local sha = repo:hash_object("blob", "FOOBAR", true)
   assert(sha == "389865bb681b358c9b102d79abd8d5f941e96551")
end

function suite.repo_create_retrieve_blob()
   local repo = assert(gall.repository.create("test/test_repo"))
   local sha = repo:hash_object("blob", "FOOBAR", true)
   assert(sha == "389865bb681b358c9b102d79abd8d5f941e96551")
   local repo2 = assert(gall.repository.new("test/test_repo"))
   local obj = repo2:get("389865bb681b358c9b102d79abd8d5f941e96551")
   assert(obj)
   assert(obj.type == "blob")
   assert(obj.content == "FOOBAR")
end

function suite.normalise_bad_ref()
   local repo = test_repo()
   local ok, msg = repo:normalise("PANTS")
   assert(not ok)
   assert(msg:find("PANTS"))
end

function suite.normalise_good_ref()
   local repo = test_repo()
   assert(repo:normalise("refs/heads/master"))
end

function suite.normalise_short_sha()
   local repo = test_repo()
   assert(repo:normalise("8b50f4e"))
end

function suite.error_normalise()
   local repo = test_repo()
   repo.path = "/DOES_NOT_EXIST"
   assert(not xpcall(function()repo:normalise("PANTS")end))
end

function suite.get_bad()
   local repo = test_repo()
   local ok, msg = repo:get("PANTS")
   assert(not ok)
   assert(msg:find("PANTS"))
end

function suite.get_ref()
   local repo = test_repo()
   assert(repo:get_ref("refs/heads/master"))
end

function suite.all_refs()
   local repo = test_repo()
   local refs, msg = repo:all_refs()
   assert(refs, msg)
   assert(refs["refs/heads/master"])
end

function suite.force_empty_tree()
   local repo = test_repo()
   local obj = assert(repo:force_empty_tree())
   assert(obj.type == "tree")
end

function suite.update_ref()
   local repo = test_repo()
   local head = repo:get("HEAD")
   assert(repo:update_ref("refs/heads/temp", head.sha))
end

function suite.update_ref_delete()
   local repo = test_repo()
   local head = repo:get("HEAD")
   assert(repo:update_ref("refs/heads/master", nil))
end

function suite.update_ref_delete_fail()
   local repo = test_repo()
   local head = repo:get("HEAD")
   local ok, msg = repo:update_ref("refs/heads/absent", nil, "whatever", head.sha)
   assert(not ok)
end

function suite.update_server_info()
   local repo = test_repo()
   assert(repo:update_server_info())
   assert(io.open("test/test_repo/.git/info/refs", "r"))
end

function suite.update_server_info_bad()
   local repo = test_repo()
   repo.path="/BONG"
   assert(not repo:update_server_info())
end

function suite.check_pass_env()
   local repo = test_repo()
   local ok, out, err = repo:_run_with_input_and_env({GIT_EDITOR="foobar"},
						     nil, gall.ll.chomp,
						     "var", "GIT_EDITOR")
   assert(ok == 0)
   assert(out == "foobar")
end

function suite.merge_base()
   local repo = test_repo()
   local sha_1 = "dbd507be22d1e8933008f453ec62e9a6fbd8c832"
   local sha_2 = "8b50f4e456886de10e5f40f10991a4451b64aea3"
   local sha_b = "b972b3345490a898f46df143a7285cb7840b9845"
   assert(repo:merge_base(sha_1, sha_2) == sha_b)
end

function suite.merge_base_all()
   local repo = test_repo()
   local sha_1 = "dbd507be22d1e8933008f453ec62e9a6fbd8c832"
   local sha_2 = "8b50f4e456886de10e5f40f10991a4451b64aea3"
   local sha_b = "b972b3345490a898f46df143a7285cb7840b9845"
   assert(repo:merge_base(sha_1, sha_2, true) == sha_b)
end

function suite.merge_base_badsha()
   local repo = test_repo()
   local sha_1 = "dbd507be22d1e8933008f453ec62e9a6fbd8c833"
   local sha_2 = "8b50f4e456886de10e5f40f10991a4451b64aea3"
   local ok, msg = repo:merge_base(sha_1, sha_2)
   assert(not ok)
end

function suite.merge_base_nobase()
   local repo = test_repo()
   local sha_1 = "dbd507be22d1e8933008f453ec62e9a6fbd8c832"
   local sha_2 = "ca4e324f8a86ed08d3467a1588dc01a8609a4004"
   local ok, msg = repo:merge_base(sha_1, sha_2)
   assert(ok == true)
end

function suite.merge_base_annotated_tags()
   local repo = test_repo()
   local sha_1 = "annotated-1"
   local sha_2 = "annotated-2"
   local sha_b = "b972b3345490a898f46df143a7285cb7840b9845"
   assert(repo:merge_base(sha_1, sha_2) == sha_b)
end

function suite.merge_base_lorries_regression()
   local repo = test_repo("lorries.git")
   local sha_1 = "738022ab867407fc9e906e89268043f72179730a"
   local sha_2 = "2f0995c6c852c9b9d6ce584f3b9f38a981a40cf3"
   local sha_b = "738022ab867407fc9e906e89268043f72179730a"
   assert(repo:merge_base(sha_1, sha_2) == sha_b)
end

function suite.ana_website_regression()
   assert(test_repo("website.git"))
end

function suite.rev_list()
   local repo = test_repo()
   local sha_new = "0b65c32b6a5277ff0e75ddad9e3914148914042d"
   local sha_old = "b972b3345490a898f46df143a7285cb7840b9845"
   local rlist = assert(repo:rev_list(sha_old, sha_new))
end

function suite.rev_list_backward()
   local repo = test_repo()
   local sha_new = "0b65c32b6a5277ff0e75ddad9e3914148914042d"
   local sha_old = "b972b3345490a898f46df143a7285cb7840b9845"
   local rlist = assert(repo:rev_list(sha_new, sha_old) == true)
end

function suite.rev_list_first()
   local repo = test_repo()
   local sha_new = "0b65c32b6a5277ff0e75ddad9e3914148914042d"
   local sha_old = "b972b3345490a898f46df143a7285cb7840b9845"
   local rlist = assert(repo:rev_list(sha_old, sha_new, true))
end

function suite.rev_list_bad()
   local repo = test_repo()
   local sha_new = "0b65c32b6a5277ff0e75ddad9e3914148914042e"
   local sha_old = "b972b3345490a898f46df143a7285cb7840b9845"
   assert(not repo:rev_list(sha_old, sha_new))
end

function suite.symbolic_ref()
   local repo = test_repo()
   local ok, ref = repo:symbolic_ref "HEAD"
   assert(ok)
   assert(ref == "refs/heads/master")
end

function suite.symbolic_ref_not_symbolic()
   local repo = test_repo()
   local ok, ref = repo:symbolic_ref "refs/heads/master"
   assert(not ok)
end

function suite.symbolic_ref_bad_name()
   local repo = test_repo()
   local ok, ref = repo:symbolic_ref "refs"
   assert(ok == nil)
   assert(ref:find("No such ref"))
end

function suite.symbolic_ref_set()
   local repo = test_repo()
   local ok = repo:symbolic_ref("HEAD", "refs/heads/signed")
   assert(ok)
   local ok, ref = repo:symbolic_ref "HEAD"
   assert(ok)
   assert(ref == "refs/heads/signed")
end

function suite.symbolic_ref_set_bad()
   local repo = test_repo()
   local ok, msg = repo:symbolic_ref("refs", "refs/heads/signed")
   assert(ok == nil)
end

function suite.config_read()
   local repo = test_repo()
   local ok, conf = repo:config("core.bare")
   assert(ok)
   assert(conf == "false")
end

function suite.config_write()
   local repo = test_repo()
   local ok = repo:config("gall.test", "thingy")
   local ok, conf = repo:config("gall.test")
   assert(ok)
   assert(conf == "thingy")
end

local count_ok = 0
for _, testname in ipairs(testnames) do
--   print("Run: " .. testname)
   local ok, err = xpcall(suite[testname], debug.traceback)
   if not ok then
      print(err)
      print()
   else
      count_ok = count_ok + 1
   end
end

print(tostring(count_ok) .. "/" .. tostring(#testnames) .. " [" .. tostring(total_asserts) .. "] OK")

os.exit(count_ok == #testnames and 0 or 1)
