git-annex/Command/PreCommit.hs
Joey Hess 5df1b2b36e
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
pre-commit-annex.

Note that the hook files take precience over the git config, since the git
config can includ global config which should be overridden by local config.

These new git configs are probably not super useful. Especially the
pre-commit-annex hook is there to install scripts to instead of the
pre-commit hook, since git-annex installs that hook itself. So why would
someone want to use a git config for that? Only reason I can think of would
be in a global git config. Or possibly because it's easier to set a git
config than write a hook script, on an OS like Windows.

The real reason I'm adding these is as groundwork for making other
annex.*-command git configs also be available as hook scripts. I want
to avoid having some things available as only git hooks and others as
both gitconfigs and git hooks. (It seems that some annex.*-command configs
don't translate to git hooks though.)

In the man page, moved documentation of the hooks to be next to the
documentation of the git configs. This is to avoid repitition.
2025-01-10 13:27:51 -04:00

88 lines
2.5 KiB
Haskell

{- git-annex command
-
- Copyright 2010-2024 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
{-# LANGUAGE CPP #-}
module Command.PreCommit where
import Command
import qualified Command.Fix
import qualified Command.Smudge
import Annex.Hook
import Annex.Link
import Annex.View
import Annex.View.ViewedFile
import Logs.View
import Logs.MetaData
import Types.View
import Types.MetaData
import qualified Annex
import qualified Annex.Branch
import qualified Data.Set as S
import qualified Data.Text as T
cmd :: Command
cmd = noCommit $ command "pre-commit" SectionPlumbing
"run by git pre-commit hook"
paramPaths
(withParams seek)
seek :: CmdParams -> CommandSeek
seek ps = do
let ww = WarnUnmatchWorkTreeItems "pre-commit"
l <- workTreeItems ww ps
-- fix symlinks to files being committed
flip (withFilesToBeCommitted ww) l $ \(si, f) -> commandAction $
maybe stop (Command.Fix.start Command.Fix.FixSymlinks si f)
=<< isAnnexLink f
-- after a merge conflict or git cherry-pick or stash, pointer
-- files in the worktree won't be populated, so populate them here
Command.Smudge.updateSmudged (Restage False)
runAnnexHook preCommitAnnexHook annexPreCommitCommand
-- committing changes to a view updates metadata
currentView >>= \case
Nothing -> noop
Just (v, _madj) -> do
withViewChanges
(addViewMetaData v)
(removeViewMetaData v)
-- Manually commit in this case, because
-- noCommit prevents automatic commit.
whenM (annexAlwaysCommit <$> Annex.getGitConfig) $
Annex.Branch.commit =<< Annex.Branch.commitMessage
addViewMetaData :: View -> ViewedFile -> Key -> CommandStart
addViewMetaData v f k = starting "metadata" ai si $
next $ changeMetaData k $ fromView v f
where
ai = mkActionItem (k, toRawFilePath f)
si = SeekInput []
removeViewMetaData :: View -> ViewedFile -> Key -> CommandStart
removeViewMetaData v f k = starting "metadata" ai si $
next $ changeMetaData k $ unsetMetaData $ fromView v f
where
ai = mkActionItem (k, toRawFilePath f)
si = SeekInput []
changeMetaData :: Key -> MetaData -> CommandCleanup
changeMetaData k metadata = do
showMetaDataChange metadata
addMetaData k metadata
return True
showMetaDataChange :: MetaData -> Annex ()
showMetaDataChange = showLongNote . UnquotedString . unlines . concatMap showmeta . fromMetaData
where
showmeta (f, vs) = map (showmetavalue f) $ S.toList vs
showmetavalue f v = T.unpack (fromMetaField f) <> showset v <> "=" <> decodeBS (fromMetaValue v)
showset v
| isSet v = "+"
| otherwise = "-"