Skip to content

Commit bf4ef2a

Browse files
committed
AcquireRepository will configure gpg signature
Port gpg signature logic from bash implementation. #297
1 parent f232b58 commit bf4ef2a

File tree

6 files changed

+161
-74
lines changed

6 files changed

+161
-74
lines changed

src/Elegit/Cli/Action/AcquireRepository.hs

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE LambdaCase #-}
12
{-# LANGUAGE QuasiQuotes #-}
23
module Elegit.Cli.Action.AcquireRepository
34
( cli
@@ -149,9 +150,36 @@ configureAliases cScope = do
149150
]
150151

151152

152-
-- TODO: port bash logic
153153
setupGPGSignature :: (MonadFree GA.GitF m) => m ()
154-
setupGPGSignature = pass
154+
setupGPGSignature = do
155+
whenJustM (GA.readConfig GA.LocalConfig (configName UserEmailKey)) $ \userEmail -> do
156+
GA.gpgListKeysVerbose userEmail >>= \case
157+
Nothing -> do
158+
GA.print =<< GA.formatInfo "There is no gpg key for the given email."
159+
GA.print =<< GA.formatInfo "A signature is not configured."
160+
Just gpgKeysOutput -> do
161+
mapM_ GA.print gpgKeysOutput
162+
GA.print ""
163+
GA.print =<< GA.formatInfo "From the list of GPG keys above, copy the GPG key ID you'd like to use."
164+
GA.print =<< GA.formatInfo "It will be"
165+
GA.print =<< GA.formatInfo " 3AA5C34371567BD2"
166+
GA.print =<< GA.formatInfo "for the output like this"
167+
GA.print =<< GA.formatInfo " sec 4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]"
168+
GA.print =<< GA.formatInfo " A330C91F8EC4BC7AECFA63E03AA5C34371567BD2"
169+
GA.print =<< GA.formatInfo " uid Hubot"
170+
GA.print =<< GA.formatInfo ""
171+
GA.print =<< GA.formatInfo "If you don't want to configure signature, just hit Enter button."
172+
-- TODO: We could parse IDs out of the gpg output.
173+
-- Then could ask for the index into list of keys instead?
174+
key <- GA.promptDefault "Please pass a key that has to sign objects of the current repository: " (Just "")
175+
if null key
176+
then GA.print =<< GA.formatInfo "The signature is not configured as the empty key is provided."
177+
else do
178+
GA.setConfigVerbose GA.LocalConfig "user.signingkey" key
179+
GA.setConfigVerbose GA.LocalConfig "gpg.program" "$(type -p gpg)"
180+
GA.setConfigVerbose GA.LocalConfig "commit.gpgsign" "true"
181+
GA.setConfigVerbose GA.LocalConfig "tag.forceSignAnnotated" "true"
182+
GA.setConfigVerbose GA.LocalConfig "tag.gpgSign" "true"
155183

156184

157185
-- | Execution description of the AcquireRepository action

src/Elegit/Git/Action.hs

+33-11
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,24 @@ import Universum hiding (print)
3838

3939
-- TODO: maybe, cover with tests
4040
class RenderGitCommand c where
41-
renderGC :: c -> Text
41+
commandArgs :: c -> Text
42+
toolName :: c -> Text
43+
toolName _ = "git"
44+
45+
renderGC :: RenderGitCommand c => c -> Text
46+
renderGC c = toolName c|+" "+|commandArgs c|+""
4247

4348
data GCurrentBranchData
4449
= GCurrentBranchData
4550

4651
instance RenderGitCommand GCurrentBranchData where
47-
renderGC _ = "rev-parse --abbrev-ref @"
52+
commandArgs _ = "rev-parse --abbrev-ref @"
4853

4954
newtype GBranchUpstreamData
5055
= GBranchUpstreamData { branch :: Text }
5156

5257
instance RenderGitCommand GBranchUpstreamData where
53-
renderGC (GBranchUpstreamData branchName) = "rev-parse --abbrev-ref "+|branchName|+"@{upstream}"
58+
commandArgs (GBranchUpstreamData branchName) = "rev-parse --abbrev-ref "+|branchName|+"@{upstream}"
5459

5560
data GLogData
5661
= GLogData
@@ -59,7 +64,7 @@ data GLogData
5964
, target :: Text
6065
}
6166
instance RenderGitCommand GLogData where
62-
renderGC (GLogData lType baseName targetName) = "log "+|logArg|+" "+|baseName|+".."+|targetName|+""
67+
commandArgs (GLogData lType baseName targetName) = "log "+|logArg|+" "+|baseName|+".."+|targetName|+""
6368
where
6469
logArg :: Text
6570
logArg = case lType of
@@ -69,7 +74,7 @@ newtype GStatusData
6974
= GStatusData { statusType :: StatusType }
7075

7176
instance RenderGitCommand GStatusData where
72-
renderGC (GStatusData sType) = "status "+|statusFormat|+""
77+
commandArgs (GStatusData sType) = "status "+|statusFormat|+""
7378
where
7479
statusFormat :: Text
7580
statusFormat = case sType of
@@ -78,7 +83,7 @@ instance RenderGitCommand GStatusData where
7883
data GStashListData
7984
= GStashListData
8085
instance RenderGitCommand GStashListData where
81-
renderGC _ = "stash list"
86+
commandArgs _ = "stash list"
8287

8388
data GReadConfigData
8489
= GReadConfigData
@@ -87,7 +92,7 @@ data GReadConfigData
8792
}
8893

8994
instance RenderGitCommand GReadConfigData where
90-
renderGC (GReadConfigData cScope cName) = "config "+|scopeText|+" --get "+|cName|+""
95+
commandArgs (GReadConfigData cScope cName) = "config "+|scopeText|+" --get "+|cName|+""
9196
where
9297
scopeText :: Text
9398
scopeText = case cScope of
@@ -103,7 +108,7 @@ data GSetConfigData
103108
}
104109

105110
instance RenderGitCommand GSetConfigData where
106-
renderGC (GSetConfigData cScope cName cValue) = "config "+|scopeText|+" "+|cName|+" "+|cValue|+""
111+
commandArgs (GSetConfigData cScope cName cValue) = "config "+|scopeText|+" "+|cName|+" \""+|cValue|+"\""
107112
where
108113
scopeText :: Text
109114
scopeText = case cScope of
@@ -118,7 +123,7 @@ data GUnsetConfigData
118123
}
119124

120125
instance RenderGitCommand GUnsetConfigData where
121-
renderGC (GUnsetConfigData cScope cName) = "config "+|scopeText|+" --unset "+|cName|+""
126+
commandArgs (GUnsetConfigData cScope cName) = "config "+|scopeText|+" --unset "+|cName|+""
122127
where
123128
scopeText :: Text
124129
scopeText = case cScope of
@@ -130,14 +135,21 @@ newtype GAliasesToRemoveData
130135
= GAliasesToRemoveData { scope :: ConfigScope }
131136

132137
instance RenderGitCommand GAliasesToRemoveData where
133-
renderGC (GAliasesToRemoveData cScope) = "config "+|scopeText|+" --name-only --get-regexp \"^alias.\" \"^elegant ([-a-z]+)$\""
138+
commandArgs (GAliasesToRemoveData cScope) = "config "+|scopeText|+" --name-only --get-regexp \"^alias.\" \"^elegant ([-a-z]+)$\""
134139
where
135140
scopeText :: Text
136141
scopeText = case cScope of
137142
GlobalConfig -> "--global"
138143
LocalConfig -> "--local"
139144
AutoConfig -> ""
140145

146+
newtype GGPGKeyListData
147+
= GGPGKeyListData { email :: Text }
148+
149+
instance RenderGitCommand GGPGKeyListData where
150+
toolName _ = "gpg"
151+
commandArgs (GGPGKeyListData gEmail) = "--list-secret-keys --keyid-format long "+|gEmail|+""
152+
141153
-- | The declaration of all posible actions we can do in the git action.
142154
--
143155
-- This describes the data of the action, and whether it can return any value
@@ -155,6 +167,7 @@ data GitF a
155167
| AliasesToRemove GAliasesToRemoveData (Maybe (NonEmpty Text) -> a)
156168
| SetConfig GSetConfigData a
157169
| UnsetConfig GUnsetConfigData a
170+
| GPGListKeys GGPGKeyListData (Maybe (NonEmpty Text) -> a)
158171
| Prompt Text (Maybe Text) (Text -> a)
159172
| FormatInfo Text (Text -> a)
160173
| FormatCommand Text (Text -> a)
@@ -231,6 +244,9 @@ setConfig cScope cName cValue = liftF $ SetConfig (GSetConfigData cScope cName c
231244
unsetConfig :: MonadFree GitF m => ConfigScope -> Text -> m ()
232245
unsetConfig cScope cName = liftF $ UnsetConfig (GUnsetConfigData cScope cName) ()
233246

247+
gpgListKeys :: MonadFree GitF m => Text -> m (Maybe (NonEmpty Text))
248+
gpgListKeys gEmail = liftF $ GPGListKeys (GGPGKeyListData gEmail) id
249+
234250
promptDefault :: MonadFree GitF m => Text -> Maybe Text -> m Text
235251
promptDefault pText pDefault = liftF $ Prompt pText pDefault id
236252

@@ -246,7 +262,7 @@ print content = liftF $ PrintText content ()
246262
-- Derived actions
247263

248264
formatGitCommand :: (RenderGitCommand gc, MonadFree GitF m) => gc -> m Text
249-
formatGitCommand gc = formatCommand ("git "+|renderGC gc|+"")
265+
formatGitCommand gc = formatCommand (renderGC gc)
250266

251267
setConfigVerbose :: MonadFree GitF m => ConfigScope -> Text -> Text -> m ()
252268
setConfigVerbose cScope cName cValue = do
@@ -258,6 +274,12 @@ unsetConfigVerbose cScope cName = do
258274
unsetConfig cScope cName
259275
print =<< formatGitCommand (GUnsetConfigData cScope cName)
260276

277+
gpgListKeysVerbose :: MonadFree GitF m => Text -> m (Maybe (NonEmpty Text))
278+
gpgListKeysVerbose gEmail = do
279+
gpgKeys <- gpgListKeys gEmail
280+
print =<< formatGitCommand (GGPGKeyListData gEmail)
281+
return gpgKeys
282+
261283
freshestDefaultBranch :: MonadFree GitF m => m Text
262284
freshestDefaultBranch = do
263285
-- TODO: Port bash logic

src/Elegit/Git/Exec.hs

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import Data.Text (stripEnd)
55
import Elegit.Git.Action
66
import Fmt
77
import GHC.IO.Handle (hFlush)
8-
import System.Process.Typed (ExitCode (ExitFailure, ExitSuccess), proc, readProcess)
9-
import Universum
8+
import System.Process.Typed (ExitCode (ExitFailure, ExitSuccess), readProcess, shell)
9+
import Universum as U
1010

1111

1212
newtype GitExecT m a
@@ -24,6 +24,7 @@ data GitCommand
2424
| GCSC GSetConfigData
2525
| GCUC GUnsetConfigData
2626
| GCATR GAliasesToRemoveData
27+
| GCGKL GGPGKeyListData
2728

2829

2930
-- TODO: cover with tests
@@ -37,6 +38,7 @@ renderGitCommand (GCRC gc) = renderGC gc
3738
renderGitCommand (GCSC gc) = renderGC gc
3839
renderGitCommand (GCUC gc) = renderGC gc
3940
renderGitCommand (GCATR gc) = renderGC gc
41+
renderGitCommand (GCGKL gc) = renderGC gc
4042

4143

4244
class Monad m => MonadGitExec m where
@@ -47,7 +49,8 @@ class Monad m => MonadGitExec m where
4749

4850
instance MonadIO m => MonadGitExec (GitExecT m) where
4951
execGit gc = do
50-
(eCode, outputBS, _errBS) <- readProcess $ proc "git" (toString <$> words (renderGitCommand gc))
52+
let shellString = toString (renderGitCommand gc)
53+
(eCode, outputBS, _errBS) <- readProcess $ shell ("git "+|shellString|+"")
5154
case eCode of
5255
-- TODO: Handle error codes per `gc`
5356
ExitFailure _ -> do

src/Elegit/Git/Runner/Real.hs

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ executeGitF arg = case arg of
4141
stashes <- lines . fromMaybe "" <$> execGit (GCSL gc)
4242
return $ next stashes
4343

44+
GA.GPGListKeys gc next -> do
45+
mGpgKeys <- execGit (GCGKL gc)
46+
return $ next (mGpgKeys >>= nonEmpty . lines)
4447
GA.AliasesToRemove gc next -> do
4548
oldAliasesM <- execGit (GCATR gc)
4649
return $ next (oldAliasesM >>= nonEmpty . lines)

src/Elegit/Git/Runner/Simulated.hs

+4
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ collectImpureCommandsF cmd = case cmd of
156156
[ fmt "stash@{"+||i||+"}: "+|(stash^.gsName)|+" on "+|(stash^.gsBranchName)|+"" | (i, stash) <- zip [(0 :: Int)..] stashes
157157
] -- this is excessive, I guess? @teggotic
158158

159+
GA.GPGListKeys (GA.GGPGKeyListData _email) next -> do
160+
-- Ideally we want to see this
161+
return $ next (Just ("3AA5C34371567BD2":|[]))
162+
159163
GA.AliasesToRemove (GA.GAliasesToRemoveData cScope) next -> do
160164
case cScope of
161165
GA.LocalConfig -> do

0 commit comments

Comments
 (0)