added hooks corresponding to annex.*-command
* Added freezecontent-annex and thawcontent-annex hooks that correspond to the git configs annex.freezecontent and annex.thawcontent. * Added secure-erase-annex hook that corresponds to the git config annex.secure-erase-command. * Added commitmessage-annex hook that corresponds to the git config annex.commitmessage-command. * Added http-headers-annex hook that corresponds to the git config annex.http-headers-command. that correspond to the post-update-annex and pre-commit-annex hooks. The use case for these is eg, setting up a git repository that is run in a container, where the easiest way to provide a script is by putting it in .git/hooks/, rather than copying it into the container in a way that puts it in PATH. This is all the ones that make sense to add for annex.*-config git configs. annex.youtube-dl-command is not a hook, it's telling git-annex what command to run. So is annex.shared-sop-command. So omitted those. May later also want to add hooks corresponding to `remote.<name>.annex-cost-command` etc. Sponsored-by: the NIH-funded NICEMAN (ReproNim TR&D3) project
This commit is contained in:
parent
5df1b2b36e
commit
a73fa77417
11 changed files with 131 additions and 53 deletions
|
@ -521,12 +521,10 @@ createMessage :: Annex String
|
||||||
createMessage = fromMaybe "branch created" <$> getCommitMessage
|
createMessage = fromMaybe "branch created" <$> getCommitMessage
|
||||||
|
|
||||||
getCommitMessage :: Annex (Maybe String)
|
getCommitMessage :: Annex (Maybe String)
|
||||||
getCommitMessage = do
|
getCommitMessage =
|
||||||
config <- Annex.getGitConfig
|
outputOfAnnexHook commitMessageAnnexHook annexCommitMessageCommand
|
||||||
case annexCommitMessageCommand config of
|
<|>
|
||||||
Nothing -> return (annexCommitMessage config)
|
(annexCommitMessage <$> Annex.getGitConfig)
|
||||||
Just cmd -> catchDefaultIO (annexCommitMessage config) $
|
|
||||||
Just <$> liftIO (readProcess "sh" ["-c", cmd])
|
|
||||||
|
|
||||||
{- Stages the journal, and commits staged changes to the branch. -}
|
{- Stages the journal, and commits staged changes to the branch. -}
|
||||||
commit :: String -> Annex ()
|
commit :: String -> Annex ()
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
module Annex.Content.LowLevel where
|
module Annex.Content.LowLevel where
|
||||||
|
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
|
import Annex.Hook
|
||||||
import Logs.Transfer
|
import Logs.Transfer
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Utility.DiskFree
|
import Utility.DiskFree
|
||||||
|
@ -25,11 +26,8 @@ import System.PosixCompat.Files (linkCount)
|
||||||
- File may or may not be deleted at the end; caller is responsible for
|
- File may or may not be deleted at the end; caller is responsible for
|
||||||
- making sure it's deleted. -}
|
- making sure it's deleted. -}
|
||||||
secureErase :: RawFilePath -> Annex ()
|
secureErase :: RawFilePath -> Annex ()
|
||||||
secureErase file = maybe noop go =<< annexSecureEraseCommand <$> Annex.getGitConfig
|
secureErase = void . runAnnexPathHook "%file"
|
||||||
where
|
secureEraseAnnexHook annexSecureEraseCommand
|
||||||
go basecmd = void $ liftIO $
|
|
||||||
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
|
|
||||||
gencmd = massReplace [ ("%file", shellEscape (fromRawFilePath file)) ]
|
|
||||||
|
|
||||||
data LinkedOrCopied = Linked | Copied
|
data LinkedOrCopied = Linked | Copied
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
- git-annex not change, otherwise removing old hooks using an old
|
- git-annex not change, otherwise removing old hooks using an old
|
||||||
- version of the script would fail.
|
- version of the script would fail.
|
||||||
-
|
-
|
||||||
- Copyright 2013-2019 Joey Hess <id@joeyh.name>
|
- Copyright 2013-2025 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
- Licensed under the GNU AGPL version 3 or higher.
|
- Licensed under the GNU AGPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
@ -48,6 +48,21 @@ preCommitAnnexHook = Git.Hook "pre-commit-annex" "" []
|
||||||
postUpdateAnnexHook :: Git.Hook
|
postUpdateAnnexHook :: Git.Hook
|
||||||
postUpdateAnnexHook = Git.Hook "post-update-annex" "" []
|
postUpdateAnnexHook = Git.Hook "post-update-annex" "" []
|
||||||
|
|
||||||
|
freezeContentAnnexHook :: Git.Hook
|
||||||
|
freezeContentAnnexHook = Git.Hook "freezecontent-annex" "" []
|
||||||
|
|
||||||
|
thawContentAnnexHook :: Git.Hook
|
||||||
|
thawContentAnnexHook = Git.Hook "thawcontent-annex" "" []
|
||||||
|
|
||||||
|
secureEraseAnnexHook :: Git.Hook
|
||||||
|
secureEraseAnnexHook = Git.Hook "secure-erase-annex" "" []
|
||||||
|
|
||||||
|
commitMessageAnnexHook :: Git.Hook
|
||||||
|
commitMessageAnnexHook = Git.Hook "commitmessage-annex" "" []
|
||||||
|
|
||||||
|
httpHeadersAnnexHook :: Git.Hook
|
||||||
|
httpHeadersAnnexHook = Git.Hook "http-headers-annex" "" []
|
||||||
|
|
||||||
mkHookScript :: String -> String
|
mkHookScript :: String -> String
|
||||||
mkHookScript s = unlines
|
mkHookScript s = unlines
|
||||||
[ shebang
|
[ shebang
|
||||||
|
@ -69,23 +84,26 @@ hookWarning h msg = do
|
||||||
warning $ UnquotedString $
|
warning $ UnquotedString $
|
||||||
Git.hookName h ++ " hook (" ++ Git.hookFile h r ++ ") " ++ msg
|
Git.hookName h ++ " hook (" ++ Git.hookFile h r ++ ") " ++ msg
|
||||||
|
|
||||||
{- Runs a hook. To avoid checking if the hook exists every time,
|
{- To avoid checking if the hook exists every time, the existing hooks
|
||||||
- the existing hooks are cached. -}
|
- are cached. -}
|
||||||
runAnnexHook :: Git.Hook -> (GitConfig -> Maybe String) -> Annex ()
|
doesAnnexHookExist :: Git.Hook -> Annex Bool
|
||||||
runAnnexHook hook commandcfg = do
|
doesAnnexHookExist hook = do
|
||||||
m <- Annex.getState Annex.existinghooks
|
m <- Annex.getState Annex.existinghooks
|
||||||
case M.lookup hook m of
|
case M.lookup hook m of
|
||||||
Just True -> runhook
|
Just exists -> return exists
|
||||||
Just False -> runcommandcfg
|
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
exists <- inRepo $ Git.hookExists hook
|
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 }
|
||||||
if exists
|
return exists
|
||||||
then runhook
|
|
||||||
else runcommandcfg
|
runAnnexHook :: Git.Hook -> (GitConfig -> Maybe String) -> Annex ()
|
||||||
|
runAnnexHook hook commandcfg = ifM (doesAnnexHookExist hook)
|
||||||
|
( runhook
|
||||||
|
, runcommandcfg
|
||||||
|
)
|
||||||
where
|
where
|
||||||
runhook = unlessM (inRepo $ Git.runHook hook) $ do
|
runhook = unlessM (inRepo $ Git.runHook boolSystem hook []) $ do
|
||||||
h <- fromRepo $ Git.hookFile hook
|
h <- fromRepo $ Git.hookFile hook
|
||||||
commandfailed h
|
commandfailed h
|
||||||
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
|
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
|
||||||
|
@ -94,3 +112,29 @@ runAnnexHook hook commandcfg = do
|
||||||
commandfailed command
|
commandfailed command
|
||||||
Nothing -> noop
|
Nothing -> noop
|
||||||
commandfailed c = warning $ UnquotedString $ c ++ " failed"
|
commandfailed c = warning $ UnquotedString $ c ++ " failed"
|
||||||
|
|
||||||
|
runAnnexPathHook :: String -> Git.Hook -> (GitConfig -> Maybe String) -> RawFilePath -> Annex Bool
|
||||||
|
runAnnexPathHook pathtoken hook commandcfg p = ifM (doesAnnexHookExist hook)
|
||||||
|
( runhook
|
||||||
|
, runcommandcfg
|
||||||
|
)
|
||||||
|
where
|
||||||
|
runhook = inRepo $ Git.runHook boolSystem hook [ File (fromRawFilePath p) ]
|
||||||
|
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
|
||||||
|
Just basecmd -> liftIO $
|
||||||
|
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
|
||||||
|
Nothing -> return True
|
||||||
|
gencmd = massReplace [ (pathtoken, shellEscape (fromRawFilePath p)) ]
|
||||||
|
|
||||||
|
outputOfAnnexHook :: Git.Hook -> (GitConfig -> Maybe String) -> Annex (Maybe String)
|
||||||
|
outputOfAnnexHook hook commandcfg = ifM (doesAnnexHookExist hook)
|
||||||
|
( runhook
|
||||||
|
, runcommandcfg
|
||||||
|
)
|
||||||
|
where
|
||||||
|
runhook = inRepo (Git.runHook runhook' hook [])
|
||||||
|
runhook' c ps = Just <$> readProcess c (toCommand ps)
|
||||||
|
runcommandcfg = commandcfg <$> Annex.getGitConfig >>= \case
|
||||||
|
Just command -> liftIO $
|
||||||
|
Just <$> readProcess "sh" ["-c", command]
|
||||||
|
Nothing -> return Nothing
|
||||||
|
|
|
@ -33,6 +33,7 @@ module Annex.Perms (
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Annex.Common
|
import Annex.Common
|
||||||
|
import Annex.Hook
|
||||||
import Utility.FileMode
|
import Utility.FileMode
|
||||||
import Git
|
import Git
|
||||||
import Git.ConfigTypes
|
import Git.ConfigTypes
|
||||||
|
@ -340,24 +341,24 @@ modifyContentDirWhenExists f a = do
|
||||||
either throwM return v
|
either throwM return v
|
||||||
|
|
||||||
hasFreezeHook :: Annex Bool
|
hasFreezeHook :: Annex Bool
|
||||||
hasFreezeHook = isJust . annexFreezeContentCommand <$> Annex.getGitConfig
|
hasFreezeHook =
|
||||||
|
(isJust . annexFreezeContentCommand <$> Annex.getGitConfig)
|
||||||
|
<||>
|
||||||
|
(doesAnnexHookExist freezeContentAnnexHook)
|
||||||
|
|
||||||
hasThawHook :: Annex Bool
|
hasThawHook :: Annex Bool
|
||||||
hasThawHook = isJust . annexThawContentCommand <$> Annex.getGitConfig
|
hasThawHook =
|
||||||
|
(isJust . annexThawContentCommand <$> Annex.getGitConfig)
|
||||||
|
<||>
|
||||||
|
(doesAnnexHookExist thawContentAnnexHook)
|
||||||
|
|
||||||
freezeHook :: RawFilePath -> Annex ()
|
freezeHook :: RawFilePath -> Annex ()
|
||||||
freezeHook p = maybe noop go =<< annexFreezeContentCommand <$> Annex.getGitConfig
|
freezeHook = void . runAnnexPathHook "%path"
|
||||||
where
|
freezeContentAnnexHook annexFreezeContentCommand
|
||||||
go basecmd = void $ liftIO $
|
|
||||||
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
|
|
||||||
gencmd = massReplace [ ("%path", shellEscape (fromRawFilePath p)) ]
|
|
||||||
|
|
||||||
thawHook :: RawFilePath -> Annex ()
|
thawHook :: RawFilePath -> Annex ()
|
||||||
thawHook p = maybe noop go =<< annexThawContentCommand <$> Annex.getGitConfig
|
thawHook = void . runAnnexPathHook "%path"
|
||||||
where
|
thawContentAnnexHook annexThawContentCommand
|
||||||
go basecmd = void $ liftIO $
|
|
||||||
boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
|
|
||||||
gencmd = massReplace [ ("%path", shellEscape (fromRawFilePath p)) ]
|
|
||||||
|
|
||||||
{- Calculate mode to use for a directory from the mode to use for a file.
|
{- Calculate mode to use for a directory from the mode to use for a file.
|
||||||
-
|
-
|
||||||
|
|
|
@ -35,6 +35,7 @@ import Annex.Common
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import qualified Utility.Url as U
|
import qualified Utility.Url as U
|
||||||
import qualified Utility.Url.Parse as U
|
import qualified Utility.Url.Parse as U
|
||||||
|
import Annex.Hook
|
||||||
import Utility.Hash (IncrementalVerifier)
|
import Utility.Hash (IncrementalVerifier)
|
||||||
import Utility.IPAddress
|
import Utility.IPAddress
|
||||||
import Network.HTTP.Client.Restricted
|
import Network.HTTP.Client.Restricted
|
||||||
|
@ -75,9 +76,11 @@ getUrlOptions = Annex.getState Annex.urloptions >>= \case
|
||||||
<*> pure (Just (\u -> "Configuration of annex.security.allowed-url-schemes does not allow accessing " ++ show u))
|
<*> pure (Just (\u -> "Configuration of annex.security.allowed-url-schemes does not allow accessing " ++ show u))
|
||||||
<*> pure U.noBasicAuth
|
<*> pure U.noBasicAuth
|
||||||
|
|
||||||
headers = annexHttpHeadersCommand <$> Annex.getGitConfig >>= \case
|
headers =
|
||||||
Just cmd -> lines <$> liftIO (readProcess "sh" ["-c", cmd])
|
outputOfAnnexHook httpHeadersAnnexHook annexHttpHeadersCommand
|
||||||
Nothing -> annexHttpHeaders <$> Annex.getGitConfig
|
>>= \case
|
||||||
|
Just output -> pure (lines output)
|
||||||
|
Nothing -> annexHttpHeaders <$> Annex.getGitConfig
|
||||||
|
|
||||||
checkallowedaddr = words . annexAllowedIPAddresses <$> Annex.getGitConfig >>= \case
|
checkallowedaddr = words . annexAllowedIPAddresses <$> Annex.getGitConfig >>= \case
|
||||||
["all"] -> do
|
["all"] -> do
|
||||||
|
|
12
CHANGELOG
12
CHANGELOG
|
@ -11,9 +11,17 @@ git-annex (10.20250103) UNRELEASED; urgency=medium
|
||||||
* git-remote-annex: Use enableremote rather than initremote.
|
* git-remote-annex: Use enableremote rather than initremote.
|
||||||
* Windows: Fix permission denied error when dropping files that
|
* Windows: Fix permission denied error when dropping files that
|
||||||
have the readonly attribute set.
|
have the readonly attribute set.
|
||||||
|
* Added freezecontent-annex and thawcontent-annex hooks that
|
||||||
|
correspond to the git configs annex.freezecontent and
|
||||||
|
annex.thawcontent.
|
||||||
|
* Added secure-erase-annex hook that corresponds to the git config
|
||||||
|
annex.secure-erase-command.
|
||||||
|
* Added commitmessage-annex hook that corresponds to the git config
|
||||||
|
annex.commitmessage-command.
|
||||||
|
* Added http-headers-annex hook that corresponds to the git config
|
||||||
|
annex.http-headers-command.
|
||||||
* Added git configs annex.post-update-command and annex.pre-commit-command
|
* Added git configs annex.post-update-command and annex.pre-commit-command
|
||||||
that correspond to the git-annex hook scripts post-update-annex and
|
that correspond to the post-update-annex and pre-commit-annex hooks.
|
||||||
pre-commit-annex.
|
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Fri, 03 Jan 2025 14:30:38 -0400
|
-- Joey Hess <id@joeyh.name> Fri, 03 Jan 2025 14:30:38 -0400
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,8 @@ hookExists h r = do
|
||||||
doesFileExist f
|
doesFileExist f
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
runHook :: Hook -> Repo -> IO Bool
|
runHook :: (FilePath -> [CommandParam] -> IO a) -> Hook -> [CommandParam] -> Repo -> IO a
|
||||||
runHook h r = do
|
runHook runner h ps r = do
|
||||||
let f = hookFile h r
|
let f = hookFile h r
|
||||||
(c, ps) <- findShellCommand f
|
(c, cps) <- findShellCommand f
|
||||||
boolSystem c ps
|
runner c (cps ++ ps)
|
||||||
|
|
|
@ -1154,17 +1154,20 @@ repository, using [[git-annex-config]]. See its man page for a list.)
|
||||||
|
|
||||||
This command is run and its output is used as the commit message to the
|
This command is run and its output is used as the commit message to the
|
||||||
git-annex branch.
|
git-annex branch.
|
||||||
|
|
||||||
|
Alternatively, a hook script can be installed in
|
||||||
|
`.git/hooks/commitmessage-annex`
|
||||||
|
|
||||||
* `annex.post-update-command`
|
* `annex.post-update-command`
|
||||||
|
|
||||||
This command is run after git-annex updates the git-annex branch.
|
This command is run after git-annex updates the git-annex branch.
|
||||||
|
|
||||||
Alternatively, a hook script can be installed in
|
|
||||||
`.git/hooks/post-update-annex`
|
|
||||||
|
|
||||||
When publishing a git-annex repository by http, this can be used to run
|
When publishing a git-annex repository by http, this can be used to run
|
||||||
`git update-server-info`
|
`git update-server-info`
|
||||||
|
|
||||||
|
Alternatively, a hook script can be installed in
|
||||||
|
`.git/hooks/post-update-annex`
|
||||||
|
|
||||||
* `annex.pre-commit-command`
|
* `annex.pre-commit-command`
|
||||||
|
|
||||||
This command is run whenever a commit is made to the HEAD branch of
|
This command is run whenever a commit is made to the HEAD branch of
|
||||||
|
@ -1422,21 +1425,28 @@ repository, using [[git-annex-config]]. See its man page for a list.)
|
||||||
erased.
|
erased.
|
||||||
|
|
||||||
For example, to use the wipe command, set it to `wipe -f %file`.
|
For example, to use the wipe command, set it to `wipe -f %file`.
|
||||||
|
|
||||||
|
Alternatively to setting the git config, a hook script can be installed
|
||||||
|
in `.git/hooks/secure-erase-annex`
|
||||||
|
|
||||||
* `annex.freezecontent-command`, `annex.thawcontent-command`
|
* `annex.freezecontent-command`, `annex.thawcontent-command`
|
||||||
|
|
||||||
Usually the write permission bits are unset to protect annexed objects
|
Usually the write permission bits are unset to protect annexed objects
|
||||||
from being modified or deleted. The freezecontent-command is run after
|
from being modified or deleted. Freezecontent is run after
|
||||||
git-annex has removed (or attempted to remove) the write bit, and can
|
git-annex has removed (or attempted to remove) the write bit, and can
|
||||||
be used to prevent writing in some other way.
|
be used to prevent writing in some other way.
|
||||||
The thawcontent-command should undo its effect, and is run before
|
Tawcontent should undo its effect, and is run before
|
||||||
git-annex restores the write bit.
|
git-annex restores the write bit.
|
||||||
|
|
||||||
In the command line, %path is replaced with the file or directory to
|
In the command line, %path is replaced with the file or directory to
|
||||||
operate on.
|
operate on.
|
||||||
|
|
||||||
(When annex.crippledfilesystem is set, git-annex will not try to
|
(When annex.crippledfilesystem is set, git-annex will not try to
|
||||||
remove/restore the write bit, but it will still run these hooks.)
|
remove/restore the write bit, but it will still run freezecontent and
|
||||||
|
thawcontent.)
|
||||||
|
|
||||||
|
Alternatively to setting the git config, hook scripts can be installed
|
||||||
|
in `.git/hooks/freezecontent-annex` and `.git/hooks/thawcontent-annex`.
|
||||||
|
|
||||||
* `annex.tune.objecthash1`, `annex.tune.objecthashlower`, `annex.tune.branchhash1`
|
* `annex.tune.objecthash1`, `annex.tune.objecthashlower`, `annex.tune.branchhash1`
|
||||||
|
|
||||||
|
@ -2065,6 +2075,9 @@ Remotes are configured using these settings in `.git/config`.
|
||||||
|
|
||||||
If set, the command is run and each line of its output is used as a HTTP
|
If set, the command is run and each line of its output is used as a HTTP
|
||||||
header. This overrides annex.http-headers.
|
header. This overrides annex.http-headers.
|
||||||
|
|
||||||
|
Alternatively, a hook script can be installed in
|
||||||
|
`.git/hooks/http-headers-annex`
|
||||||
|
|
||||||
* `annex.security.allowed-url-schemes`
|
* `annex.security.allowed-url-schemes`
|
||||||
|
|
||||||
|
|
|
@ -25,3 +25,5 @@ I wonder if there could be a way added to be able to specify them relative to th
|
||||||
|
|
||||||
[[!meta author=yoh]]
|
[[!meta author=yoh]]
|
||||||
[[!tag projects/repronim]]
|
[[!tag projects/repronim]]
|
||||||
|
|
||||||
|
> [[done]] --[[Joey]]
|
||||||
|
|
|
@ -23,12 +23,11 @@ hook that git-annex writes. But, it seems worth having the git config just
|
||||||
for consistency.
|
for consistency.
|
||||||
|
|
||||||
There are some things like annex.youtube-dl-command and
|
There are some things like annex.youtube-dl-command and
|
||||||
annex.http-headers-command that are configuring commands for git-annex to
|
annex.shared-sop-command that are configuring commands for git-annex to
|
||||||
run, and are not really hooks per se.
|
run, and are not really hooks per se.
|
||||||
|
|
||||||
And it does not make sense to have hook scripts that a specific to a given
|
And it does not make sense to have hook scripts that a specific to a given
|
||||||
remote corresponding to configs like `remote.name.annex-cost-command`.
|
remote corresponding to configs like `remote.name.annex-cost-command`.
|
||||||
Instead it might make sense to have a `.git/hooks/remote-cost-annex` that
|
Instead there could be a single `.git/hooks/remote-cost-annex` that
|
||||||
is passed the name of the remote, but that bridge can be crossed if we
|
is passed the name of the remote.
|
||||||
come to it.
|
|
||||||
"""]]
|
"""]]
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
[[!comment format=mdwn
|
||||||
|
username="joey"
|
||||||
|
subject="""comment 7"""
|
||||||
|
date="2025-01-10T18:50:07Z"
|
||||||
|
content="""
|
||||||
|
Implemented hooks: freezecontent-annex, thawcontent-annex,
|
||||||
|
secure-erase-annex, commitmessage-annex, http-headers-annex
|
||||||
|
|
||||||
|
That leaves only `remote.name.annex-cost-command` and similar git configs
|
||||||
|
that don't have hooks. And a few like annex.youtube-dl-command that are not
|
||||||
|
really equivilant to hooks.
|
||||||
|
"""]]
|
Loading…
Add table
Add a link
Reference in a new issue