Windows: Fix running of the pre-commit-annex hook.
This commit is contained in:
parent
d818e4c06c
commit
6035f94666
5 changed files with 83 additions and 11 deletions
|
@ -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"
|
||||
|
|
41
Git/Hook.hs
41
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, [])
|
||||
|
|
1
debian/changelog
vendored
1
debian/changelog
vendored
|
@ -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
|
||||
|
||||
|
|
27
doc/bugs/windows_isExecutable_fail.mdwn
Normal file
27
doc/bugs/windows_isExecutable_fail.mdwn
Normal file
|
@ -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]]
|
|
@ -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.
|
||||
"""]]
|
Loading…
Reference in a new issue