diff options
-rw-r--r-- | Annex/Hook.hs | 16 | ||||
-rw-r--r-- | Git/Hook.hs | 41 | ||||
-rw-r--r-- | debian/changelog | 1 | ||||
-rw-r--r-- | doc/bugs/windows_isExecutable_fail.mdwn | 27 | ||||
-rw-r--r-- | doc/tips/automatically_adding_metadata/comment_6_34f0c55d09ddee3de642f6b25a9f6269._comment | 9 |
5 files changed, 83 insertions, 11 deletions
diff --git a/Annex/Hook.hs b/Annex/Hook.hs index 4848e2d61..44542c12d 100644 --- a/Annex/Hook.hs +++ b/Annex/Hook.hs @@ -16,7 +16,6 @@ import qualified Git.Hook as Git import Config import qualified Annex import Utility.Shell -import Utility.FileMode import qualified Data.Map as M @@ -53,19 +52,16 @@ hookWarning h msg = do - the existing hooks are cached. -} runAnnexHook :: Git.Hook -> Annex () runAnnexHook hook = do - cmd <- fromRepo $ Git.hookFile hook m <- Annex.getState Annex.existinghooks case M.lookup hook m of - Just True -> run cmd + Just True -> run Just False -> noop Nothing -> do - exists <- hookexists cmd + exists <- inRepo $ Git.hookExists hook Annex.changeState $ \s -> s { Annex.existinghooks = M.insert hook exists m } - when exists $ - run cmd + when exists run where - hookexists f = liftIO $ catchBoolIO $ - isExecutable . fileMode <$> getFileStatus f - run cmd = unlessM (liftIO $ boolSystem cmd []) $ - warning $ cmd ++ " failed" + run = unlessM (inRepo $ Git.runHook hook) $ do + h <- fromRepo $ Git.hookFile hook + warning $ h ++ " failed" diff --git a/Git/Hook.hs b/Git/Hook.hs index 6245a292d..0ea9fd1e7 100644 --- a/Git/Hook.hs +++ b/Git/Hook.hs @@ -1,15 +1,20 @@ {- git hooks - - - Copyright 2013 Joey Hess <joey@kitenet.net> + - Copyright 2013-2015 Joey Hess <joey@kitenet.net> - - Licensed under the GNU GPL version 3 or higher. -} +{-# LANGUAGE CPP #-} + module Git.Hook where import Common import Git import Utility.Tmp +#ifndef mingw32_HOST_OS +import Utility.FileMode +#endif data Hook = Hook { hookName :: FilePath @@ -56,3 +61,37 @@ expectedContent :: Hook -> Repo -> IO Bool expectedContent h r = do content <- readFile $ hookFile h r return $ content == hookScript h + +hookExists :: Hook -> Repo -> IO Bool +hookExists h r = do + let f = hookFile h r + catchBoolIO $ +#ifndef mingw32_HOST_OS + isExecutable . fileMode <$> getFileStatus f +#else + doesFileExist f +#endif + +runHook :: Hook -> Repo -> IO Bool +runHook h r = do + let f = hookFile h r + (c, ps) <- findcmd f + boolSystem c ps + where +#ifndef mingw32_HOST_OS + findcmd = defcmd +#else + {- Like msysgit, parse the first line of the hook file, + - look for "#!", and dispatch the interpreter on the file. -} + findcmd f = do + l <- headMaybe . lines <$> catchDefaultIO "" (readFile f) + case l of + Just ('#':'!':rest) -> case words rest of + [] -> defcmd f + (c:ps) -> do + let ps' = map Param (ps ++ [f]) + ok <- inPath c + return (if ok then c else takeFileName c, ps') + _ -> defcmd f +#endif + defcmd f = return (f, []) diff --git a/debian/changelog b/debian/changelog index 9216968fd..bdbe2663d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,7 @@ git-annex (5.20150114) UNRELEASED; urgency=medium * Fix build failure when wget is not installed. * Fix wording of message displayed when unable to get a file that is available in untrusted repositories. + * Windows: Fix running of the pre-commit-annex hook. -- Joey Hess <id@joeyh.name> Tue, 13 Jan 2015 17:03:39 -0400 diff --git a/doc/bugs/windows_isExecutable_fail.mdwn b/doc/bugs/windows_isExecutable_fail.mdwn new file mode 100644 index 000000000..41e5b29a2 --- /dev/null +++ b/doc/bugs/windows_isExecutable_fail.mdwn @@ -0,0 +1,27 @@ +On Windows, isExecutable fails to detect a file that is indeed executable +as such. This prevents git-annex from running the pre-commit-hook +on Windows. + +getFileStatus yields a fileMode of 100666, which is +clearly a dummy mode. Not surprising, since unix-compat is partial stubs +on windows. + +Actually, isExecutable is ok (it needs to check unix modes because it is +used on file modes coming out of git). But, getFileStatus is the wrong +thing to be using on Windows to check if a hook exists and is executable. + +I don't see anything in Win32 or Win32-extras on hackage that can check +executablility. Looking at git's source, it uses `access(path, X_OK) < 0`; +haskell equivilant is System.Posix.Files.fileAccess, but the version +in unix-compat has the same problem as checking getFileStatus's fileMode. + +I think it's reasonable to assume that if a hook exists on windows, it's +intended to be executable, and try to run it. Actually, testing with +msysgit, it runs hooks whether or not they have the execute bit set! +So, done that now. + +However, now git-annex tries to run the hook but fails when it's a shell +script because #!/bin/sh is useless on windows. It looks to me like msysgit +runs "sh hook" to work around that, and it is in fact parsing the shebang +line and dispatching the interpreter. Ugh. (Also, pre-commit.bat doesn't +get run.) Ok, added this same hack to git-annex. [[done]] --[[Joey]] diff --git a/doc/tips/automatically_adding_metadata/comment_6_34f0c55d09ddee3de642f6b25a9f6269._comment b/doc/tips/automatically_adding_metadata/comment_6_34f0c55d09ddee3de642f6b25a9f6269._comment new file mode 100644 index 000000000..ab5bc7b76 --- /dev/null +++ b/doc/tips/automatically_adding_metadata/comment_6_34f0c55d09ddee3de642f6b25a9f6269._comment @@ -0,0 +1,9 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 6""" + date="2015-01-20T17:19:34Z" + content=""" +@Michele after testing, git-annex on Windows seems to not see a file that +does have the executable bit set as executable. I have opened a bug report +[[bugs/windows_isExecutable_fail]], and worked around the problem now. +"""]] |