    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