hsec-tools-0.1.0.0: app/Command/Reserve.hs
{-# LANGUAGE LambdaCase #-}
module Command.Reserve where
import Control.Monad (unless, when)
import Data.Maybe (fromMaybe)
import System.Exit (die)
import System.FilePath ((</>), (<.>))
import Security.Advisories.Git
( add
, commit
, explainGitError
, getRepoRoot
)
import Security.Advisories.Core.HsecId
( placeholder
, printHsecId
, getNextHsecId
)
import Security.Advisories.Filesystem
( dirNameAdvisories
, dirNameReserved
, isSecurityAdvisoriesRepo
, getGreatestId
)
-- | How to choose IDs when creating advisories or
-- reservations.
data IdMode
= IdModePlaceholder
-- ^ Create a placeholder ID (e.g. HSEC-0000-0000). Real IDs
-- will be assigned later.
| IdModeAuto
-- ^ Use the next available ID. This option is more likely to
-- result in conflicts when submitting advisories or reservations.
data CommitFlag = Commit | DoNotCommit
deriving (Eq)
runReserveCommand :: Maybe FilePath -> IdMode -> CommitFlag -> IO ()
runReserveCommand mPath idMode commitFlag = do
let
path = fromMaybe "." mPath
repoPath <- getRepoRoot path >>= \case
Left _ -> die "Not a git repo"
Right a -> pure a
isRepo <- isSecurityAdvisoriesRepo repoPath
unless isRepo $
die "Not a security-advisories repo"
hsid <- case idMode of
IdModePlaceholder -> pure placeholder
IdModeAuto -> do
curMax <- getGreatestId repoPath
getNextHsecId curMax
let
advisoriesPath = repoPath </> dirNameAdvisories
fileName = printHsecId hsid <.> "md"
filePath = advisoriesPath </> dirNameReserved </> fileName
writeFile filePath "" -- write empty file
when (commitFlag == Commit) $ do
let msg = printHsecId hsid <> ": reserve id"
add repoPath [filePath] >>= \case
Left e -> die $ "Failed to update Git index: " <> explainGitError e
Right _ -> pure ()
commit repoPath msg >>= \case
Left e -> die $ "Failed to create Git commit: " <> explainGitError e
Right _ -> pure ()