module Propellor.Git.VerifiedBranch where

import Propellor.Base
import Propellor.Git
import Propellor.PrivData.Paths

{- To verify origin branch commit's signature, have to convince gpg
 - to use our keyring while running git verify-tag.
 - Which has no way to pass options to gpg. Argh!
 -}
verifyOriginBranch :: String -> IO Bool
verifyOriginBranch :: String -> IO Bool
verifyOriginBranch String
originbranch = do
	let gpgconf :: String
gpgconf = String
privDataDir String -> String -> String
</> String
"gpg.conf"
	keyring <- IO String
privDataKeyring
	writeFile gpgconf $ unlines
		[ " keyring " ++ keyring
		, "no-auto-check-trustdb"
		]
	-- gpg is picky about perms
	modifyFileMode privDataDir (removeModes otherGroupModes)
	verified <- boolSystemEnv "git" [Param "verify-commit", Param originbranch]
		(Just [("GNUPGHOME", privDataDir)])
	nukeFile $ privDataDir </> "trustdb.gpg"
	nukeFile $ privDataDir </> "pubring.gpg"
	nukeFile $ privDataDir </> "gpg.conf"
	return verified

-- Returns True if HEAD is changed by fetching and merging from origin.
fetchOrigin :: IO Bool
fetchOrigin :: IO Bool
fetchOrigin = do
	fetched <- String -> IO Bool -> IO Bool
forall (m :: * -> *) r.
(MonadIO m, MonadMask m, ActionResult r, ToResult r) =>
String -> m r -> m r
actionMessage String
"Pull from central git repository" (IO Bool -> IO Bool) -> IO Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$
		String -> [CommandParam] -> IO Bool
boolSystem String
"git" [String -> CommandParam
Param String
"fetch"]
	if fetched
		then mergeOrigin
		else return False

mergeOrigin :: IO Bool
mergeOrigin :: IO Bool
mergeOrigin = do
	branchref <- IO String
getCurrentBranch
	let originbranch = String
"origin" String -> String -> String
</> String
branchref

	oldsha <- getCurrentGitSha1 branchref

	keyring <- privDataKeyring
	whenM (doesFileExist keyring) $
		ifM (verifyOriginBranch originbranch)
			( do
				putStrLn $ "git branch " ++ originbranch ++ " gpg signature verified; merging"
				hFlush stdout
				void $ boolSystem "git" [Param "merge", Param originbranch]
			, warningMessage $ "git branch " ++ originbranch ++ " is not signed with a trusted gpg key; refusing to deploy it! (Running with previous configuration instead.)"
			)

	newsha <- getCurrentGitSha1 branchref
	return $ oldsha /= newsha