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 Config
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Utility.Shell
|
import Utility.Shell
|
||||||
import Utility.FileMode
|
|
||||||
|
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
|
|
||||||
|
@ -53,19 +52,16 @@ hookWarning h msg = do
|
||||||
- the existing hooks are cached. -}
|
- the existing hooks are cached. -}
|
||||||
runAnnexHook :: Git.Hook -> Annex ()
|
runAnnexHook :: Git.Hook -> Annex ()
|
||||||
runAnnexHook hook = do
|
runAnnexHook hook = do
|
||||||
cmd <- fromRepo $ Git.hookFile hook
|
|
||||||
m <- Annex.getState Annex.existinghooks
|
m <- Annex.getState Annex.existinghooks
|
||||||
case M.lookup hook m of
|
case M.lookup hook m of
|
||||||
Just True -> run cmd
|
Just True -> run
|
||||||
Just False -> noop
|
Just False -> noop
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
exists <- hookexists cmd
|
exists <- inRepo $ Git.hookExists hook
|
||||||
Annex.changeState $ \s -> s
|
Annex.changeState $ \s -> s
|
||||||
{ Annex.existinghooks = M.insert hook exists m }
|
{ Annex.existinghooks = M.insert hook exists m }
|
||||||
when exists $
|
when exists run
|
||||||
run cmd
|
|
||||||
where
|
where
|
||||||
hookexists f = liftIO $ catchBoolIO $
|
run = unlessM (inRepo $ Git.runHook hook) $ do
|
||||||
isExecutable . fileMode <$> getFileStatus f
|
h <- fromRepo $ Git.hookFile hook
|
||||||
run cmd = unlessM (liftIO $ boolSystem cmd []) $
|
warning $ h ++ " failed"
|
||||||
warning $ cmd ++ " failed"
|
|
||||||
|
|
41
Git/Hook.hs
41
Git/Hook.hs
|
@ -1,15 +1,20 @@
|
||||||
{- git hooks
|
{- 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.
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
{-# LANGUAGE CPP #-}
|
||||||
|
|
||||||
module Git.Hook where
|
module Git.Hook where
|
||||||
|
|
||||||
import Common
|
import Common
|
||||||
import Git
|
import Git
|
||||||
import Utility.Tmp
|
import Utility.Tmp
|
||||||
|
#ifndef mingw32_HOST_OS
|
||||||
|
import Utility.FileMode
|
||||||
|
#endif
|
||||||
|
|
||||||
data Hook = Hook
|
data Hook = Hook
|
||||||
{ hookName :: FilePath
|
{ hookName :: FilePath
|
||||||
|
@ -56,3 +61,37 @@ expectedContent :: Hook -> Repo -> IO Bool
|
||||||
expectedContent h r = do
|
expectedContent h r = do
|
||||||
content <- readFile $ hookFile h r
|
content <- readFile $ hookFile h r
|
||||||
return $ content == hookScript h
|
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 build failure when wget is not installed.
|
||||||
* Fix wording of message displayed when unable to get a file that
|
* Fix wording of message displayed when unable to get a file that
|
||||||
is available in untrusted repositories.
|
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
|
-- 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…
Add table
Add a link
Reference in a new issue