Skip to content

Commit 6e71bd5

Browse files
tools: add reserve --commit option
Add the `--commit` option to the `reserve` command. When given, it commits the reservation, so that the user only needs to push and make a pull request.
1 parent b443ef6 commit 6e71bd5

File tree

3 files changed

+75
-4
lines changed

3 files changed

+75
-4
lines changed

code/hsec-tools/app/Command/Reserve.hs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22

33
module Command.Reserve where
44

5-
import Control.Monad (unless)
5+
import Control.Monad (unless, when)
66
import Data.Maybe (fromMaybe)
77
import System.Exit (die)
88
import System.FilePath ((</>), (<.>))
99

10-
import Security.Advisories.Git (getRepoRoot)
10+
import Security.Advisories.Git
11+
( add
12+
, commit
13+
, explainGitError
14+
, getRepoRoot
15+
)
1116
import Security.Advisories.HsecId
1217
( placeholder
1318
, printHsecId
@@ -30,8 +35,11 @@ data IdMode
3035
-- ^ Use the next available ID. This option is more likely to
3136
-- result in conflicts when submitting advisories or reservations.
3237

33-
runReserveCommand :: Maybe FilePath -> IdMode -> IO ()
34-
runReserveCommand mPath idMode = do
38+
data CommitFlag = Commit | DoNotCommit
39+
deriving (Eq)
40+
41+
runReserveCommand :: Maybe FilePath -> IdMode -> CommitFlag -> IO ()
42+
runReserveCommand mPath idMode commitFlag = do
3543
let
3644
path = fromMaybe "." mPath
3745
repoPath <- getRepoRoot path >>= \case
@@ -52,3 +60,12 @@ runReserveCommand mPath idMode = do
5260
fileName = printHsecId hsid <.> "md"
5361
filePath = advisoriesPath </> dirNameReserved </> fileName
5462
writeFile filePath "" -- write empty file
63+
64+
when (commitFlag == Commit) $ do
65+
let msg = printHsecId hsid <> ": reserve id"
66+
add repoPath [filePath] >>= \case
67+
Left e -> die $ "Failed to update Git index: " <> explainGitError e
68+
Right _ -> pure ()
69+
commit repoPath msg >>= \case
70+
Left e -> die $ "Failed to create Git commit: " <> explainGitError e
71+
Right _ -> pure ()

code/hsec-tools/app/Main.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ commandReserve =
5757
, ("auto", Command.Reserve.IdModeAuto)
5858
]
5959
( long "id-mode" <> help "How to assign IDs" )
60+
<*> flag
61+
Command.Reserve.DoNotCommit -- default value
62+
Command.Reserve.Commit -- active value
63+
( long "commit"
64+
<> help "Commit the reservation file"
65+
)
6066
<**> helper
6167

6268
commandCheck :: Parser (IO ())

code/hsec-tools/src/Security/Advisories/Git.hs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE LambdaCase #-}
2+
13
{-|
24
35
Helpers for deriving advisory metadata from a Git repo.
@@ -6,8 +8,11 @@ Helpers for deriving advisory metadata from a Git repo.
68
module Security.Advisories.Git
79
( AdvisoryGitInfo(..)
810
, GitError(..)
11+
, explainGitError
912
, getAdvisoryGitInfo
1013
, getRepoRoot
14+
, add
15+
, commit
1116
)
1217
where
1318

@@ -29,6 +34,19 @@ data GitError
2934
| GitTimeParseError String -- ^ unable to parse this input as a datetime
3035
deriving (Show)
3136

37+
explainGitError :: GitError -> String
38+
explainGitError = \case
39+
GitProcessError status stdout stderr ->
40+
unlines
41+
[ "git exited with status " <> show status
42+
, ">>> standard output:"
43+
, stdout
44+
, ">>> standard error:"
45+
, stderr
46+
]
47+
GitTimeParseError s ->
48+
"failed to parse time: " <> s
49+
3250
-- | Get top-level directory of the working tree.
3351
--
3452
getRepoRoot :: FilePath -> IO (Either GitError FilePath)
@@ -46,6 +64,36 @@ getRepoRoot path = do
4664
where
4765
trim = dropWhileEnd isSpace . dropWhile isSpace
4866

67+
-- | Add changes to index
68+
--
69+
add
70+
:: FilePath -- ^ path to working tree
71+
-> [FilePath] -- ^ files to update in index
72+
-> IO (Either GitError ())
73+
add path pathspecs = do
74+
(status, stdout, stderr) <- readProcessWithExitCode
75+
"git"
76+
( ["-C", path, "add"] <> pathspecs )
77+
"" -- standard input
78+
pure $ case status of
79+
ExitSuccess -> Right ()
80+
_ -> Left $ GitProcessError status stdout stderr
81+
82+
-- | Commit changes to repo.
83+
--
84+
commit
85+
:: FilePath -- ^ path to working tree
86+
-> String -- ^ commit message
87+
-> IO (Either GitError ())
88+
commit path msg = do
89+
(status, stdout, stderr) <- readProcessWithExitCode
90+
"git"
91+
["-C", path, "commit", "-m", msg]
92+
"" -- standard input
93+
pure $ case status of
94+
ExitSuccess -> Right ()
95+
_ -> Left $ GitProcessError status stdout stderr
96+
4997
getAdvisoryGitInfo :: FilePath -> IO (Either GitError AdvisoryGitInfo)
5098
getAdvisoryGitInfo path = do
5199
let (dir, file) = splitFileName path

0 commit comments

Comments
 (0)