summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex/Hook.hs16
-rw-r--r--Git/Hook.hs41
-rw-r--r--debian/changelog1
-rw-r--r--doc/bugs/windows_isExecutable_fail.mdwn27
-rw-r--r--doc/tips/automatically_adding_metadata/comment_6_34f0c55d09ddee3de642f6b25a9f6269._comment9
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.
+"""]]