diff --git a/Git.hs b/Git.hs index 043cda5ea1..9b7dccfebd 100644 --- a/Git.hs +++ b/Git.hs @@ -32,9 +32,11 @@ import qualified Data.Map as M import Data.Char import Network.URI (uriPath, uriScheme, unEscapeString) import System.Directory +import System.Posix.Files import Common import Git.Types +import Utility.FileMode {- User-visible description of a git repo. -} repoDescribe :: Repo -> String @@ -111,8 +113,12 @@ gitDir repo hookPath :: String -> Repo -> IO (Maybe FilePath) hookPath script repo = do let hook = gitDir repo "hooks" script - ok <- doesFileExist hook - return $ if ok then Just hook else Nothing + e <- doesFileExist hook + if e + then do + m <- fileMode <$> getFileStatus hook + return $ if isExecutable m then Just hook else Nothing + else return Nothing {- Path to a repository's --work-tree, that is, its top. - diff --git a/Utility/FileMode.hs b/Utility/FileMode.hs index 6c1c06e82a..571b035039 100644 --- a/Utility/FileMode.hs +++ b/Utility/FileMode.hs @@ -34,3 +34,10 @@ allowWrite f = do {- Checks if a file mode indicates it's a symlink. -} isSymLink :: FileMode -> Bool isSymLink mode = symbolicLinkMode `intersectFileModes` mode == symbolicLinkMode + +{- Checks if a file has any executable bits set. -} +isExecutable :: FileMode -> Bool +isExecutable mode = ebits `intersectFileModes` mode /= 0 + where + ebits = ownerExecuteMode `unionFileModes` + groupExecuteMode `unionFileModes` otherExecuteMode