Skip to content

Commit 5cae2db

Browse files
committed
Authorship options for stack new (#744)
1 parent cb68a39 commit 5cae2db

File tree

5 files changed

+124
-12
lines changed

5 files changed

+124
-12
lines changed

src/Stack/Config.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ configFromConfigMonoid configStackRoot mproject configMonoid@ConfigMonoid{..} =
166166
Just i -> return i
167167
let configConcurrentTests = fromMaybe True configMonoidConcurrentTests
168168

169+
let configAuthorEmail = configMonoidAuthorEmail
170+
configAuthorName = configMonoidAuthorName
171+
configScmInit = configMonoidScmInit
172+
169173
return Config {..}
170174

171175
-- | Get the directory on Windows where we should install extra programs. For

src/Stack/Constants.hs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ module Stack.Constants
3131
,hpcDirFromDir
3232
,dotHpc
3333
,objectInterfaceDir
34-
,templatesDir)
34+
,templatesDir
35+
,defaultAuthorEmail
36+
,defaultAuthorName
37+
,globalConfigPath
38+
,authorEmailKey
39+
,authorNameKey
40+
,scmInitKey)
3541
where
3642

37-
3843
import Control.Monad.Catch (MonadThrow)
3944
import Control.Monad.Reader
40-
4145
import Data.HashSet (HashSet)
4246
import qualified Data.HashSet as HashSet
4347
import Data.Text (Text)
@@ -295,3 +299,15 @@ implicitGlobalDir p =
295299
-- | Where .mix files go.
296300
dotHpc :: Path Rel Dir
297301
dotHpc = $(mkRelDir ".hpc")
302+
303+
-- | Default author email.
304+
defaultAuthorEmail :: Text
305+
defaultAuthorEmail = "[email protected]"
306+
307+
-- | Default author name.
308+
defaultAuthorName :: Text
309+
defaultAuthorName = "Example Author Name"
310+
311+
-- | Global config path.
312+
globalConfigPath :: Config -> Path Abs File
313+
globalConfigPath = (</> $(mkRelFile "stack.yaml")) . configStackRoot

src/Stack/New.hs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import Path.IO
4848
import Stack.Constants
4949
import Stack.Types
5050
import Stack.Types.TemplateName
51+
import System.Process.Run
5152
import Text.Hastache
5253
import Text.Hastache.Context
5354
import Text.ProjectTemplate
@@ -77,6 +78,7 @@ new opts = do
7778
templateText <- loadTemplate template
7879
files <- applyTemplate project absDir templateText
7980
writeTemplateFiles files
81+
runTemplateInits absDir
8082
return absDir
8183
where
8284
template = newOptsTemplate opts
@@ -107,11 +109,16 @@ loadTemplate name = do
107109

108110
-- | Apply and unpack a template into a directory.
109111
applyTemplate
110-
:: (MonadIO m, MonadThrow m)
112+
:: (MonadIO m, MonadThrow m, MonadReader r m, HasConfig r, MonadLogger m)
111113
=> PackageName -> Path Abs Dir -> Text -> m (Map (Path Abs File) LB.ByteString)
112114
applyTemplate project dir template = do
115+
config <- asks getConfig
116+
displayContext config
113117
applied <-
114-
hastacheStr defaultConfig template (mkStrContext contextFunction)
118+
hastacheStr
119+
defaultConfig
120+
template
121+
(mkStrContext (contextFunction config))
115122
files :: Map FilePath LB.ByteString <-
116123
execWriterT $
117124
yield (T.encodeUtf8 (LT.toStrict applied)) $$
@@ -123,9 +130,31 @@ applyTemplate project dir template = do
123130
do path <- parseRelFile fp
124131
return (dir </> path, bytes))
125132
(M.toList files))
126-
where contextFunction :: String -> MuType m
127-
contextFunction "name" = MuVariable (packageNameString project)
128-
contextFunction _ = MuNothing
133+
where
134+
context config =
135+
[ ("name", packageNameText project)
136+
, ( authorEmailKey
137+
, fromMaybe defaultAuthorEmail (configAuthorEmail config))
138+
, (authorNameKey, fromMaybe defaultAuthorName (configAuthorName config))]
139+
contextFunction :: Config -> String -> MuType m
140+
contextFunction config key =
141+
case lookup (T.pack key) (context config) of
142+
Nothing -> MuNothing
143+
Just value -> MuVariable value
144+
145+
-- | Display the context being used for the template.
146+
displayContext :: MonadLogger m => Config -> m ()
147+
displayContext config = do
148+
$logInfo "Using the following authorship configuration:"
149+
$logInfo
150+
(authorEmailKey <> ": " <>
151+
fromMaybe defaultAuthorEmail (configAuthorEmail config))
152+
$logInfo
153+
(authorNameKey <> ": " <>
154+
fromMaybe defaultAuthorName (configAuthorName config))
155+
$logInfo
156+
("Copy these to " <> T.pack (toFilePath (globalConfigPath config)) <>
157+
" and edit to use different values.")
129158

130159
-- | Write files to the new project directory.
131160
writeTemplateFiles
@@ -138,6 +167,21 @@ writeTemplateFiles files = do
138167
do createTree (parent fp)
139168
liftIO (LB.writeFile (toFilePath fp) bytes))
140169

170+
-- | Run any initialization functions, such as Git.
171+
runTemplateInits
172+
:: (MonadIO m, MonadReader r m, HasConfig r, MonadLogger m, MonadCatch m)
173+
=> Path Abs Dir -> m ()
174+
runTemplateInits dir = do
175+
menv <- getMinimalEnvOverride
176+
config <- asks getConfig
177+
case configScmInit config of
178+
Nothing -> return ()
179+
Just Git ->
180+
do catch
181+
(callProcess (Just dir) menv "git" ["init"])
182+
(\(_ :: ProcessExitedUnsuccessfully) ->
183+
$logInfo "git init failed to run, ignoring ...")
184+
141185
--------------------------------------------------------------------------------
142186
-- Getting templates list
143187

src/Stack/Types/Config.hs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import Control.Applicative ((<|>), (<$>), (<*>), pure)
1515
import Control.Exception
1616
import Control.Monad (liftM, mzero)
1717
import Control.Monad.Catch (MonadThrow, throwM)
18-
import Control.Monad.Reader (MonadReader, ask, asks, MonadIO, liftIO)
1918
import Control.Monad.Logger (LogLevel(..))
19+
import Control.Monad.Reader (MonadReader, ask, asks, MonadIO, liftIO)
2020
import Data.Aeson.Extended
2121
(ToJSON, toJSON, FromJSON, parseJSON, withText, withObject, object,
2222
(.=), (.:), (..:), (..:?), (..!=), Value(String, Object),
@@ -29,9 +29,9 @@ import Data.Either (partitionEithers)
2929
import Data.Hashable (Hashable)
3030
import Data.Map (Map)
3131
import qualified Data.Map as Map
32+
import Data.Monoid
3233
import Data.Set (Set)
3334
import qualified Data.Set as Set
34-
import Data.Monoid
3535
import Data.Text (Text)
3636
import qualified Data.Text as T
3737
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
@@ -40,9 +40,9 @@ import Data.Yaml (ParseException)
4040
import Distribution.System (Platform)
4141
import qualified Distribution.Text
4242
import Distribution.Version (anyVersion)
43-
import qualified Paths_stack as Meta
4443
import Network.HTTP.Client (parseUrl)
4544
import Path
45+
import qualified Paths_stack as Meta
4646
import Stack.Types.BuildPlan (SnapName, renderSnapName, parseSnapName)
4747
import Stack.Types.Docker
4848
import Stack.Types.FlagName
@@ -111,6 +111,12 @@ data Config =
111111
,configConcurrentTests :: !Bool
112112
-- ^ Run test suites concurrently
113113
,configImage :: !ImageOpts
114+
,configAuthorEmail :: !(Maybe Text)
115+
-- ^ Email of the author using stack.
116+
,configAuthorName :: !(Maybe Text)
117+
-- ^ Name of the author using stack.
118+
,configScmInit :: !(Maybe SCM)
119+
-- ^ Initialize SCM (e.g. git) when creating new projects.
114120
}
115121

116122
-- | Information on a single package index
@@ -500,6 +506,12 @@ data ConfigMonoid =
500506
-- ^ Used to override the binary installation dir
501507
,configMonoidImageOpts :: !ImageOptsMonoid
502508
-- ^ Image creation options.
509+
,configMonoidAuthorEmail :: !(Maybe Text)
510+
-- ^ Author's email address.
511+
,configMonoidAuthorName :: !(Maybe Text)
512+
-- ^ Author's name.
513+
,configMonoidScmInit :: !(Maybe SCM)
514+
-- ^ Initialize SCM (e.g. git init) when making new projects?
503515
}
504516
deriving Show
505517

@@ -523,6 +535,9 @@ instance Monoid ConfigMonoid where
523535
, configMonoidConcurrentTests = Nothing
524536
, configMonoidLocalBinPath = Nothing
525537
, configMonoidImageOpts = mempty
538+
, configMonoidAuthorEmail = mempty
539+
, configMonoidAuthorName = mempty
540+
, configMonoidScmInit = Nothing
526541
}
527542
mappend l r = ConfigMonoid
528543
{ configMonoidDockerOpts = configMonoidDockerOpts l <> configMonoidDockerOpts r
@@ -544,6 +559,9 @@ instance Monoid ConfigMonoid where
544559
, configMonoidConcurrentTests = configMonoidConcurrentTests l <|> configMonoidConcurrentTests r
545560
, configMonoidLocalBinPath = configMonoidLocalBinPath l <|> configMonoidLocalBinPath r
546561
, configMonoidImageOpts = configMonoidImageOpts l <> configMonoidImageOpts r
562+
, configMonoidAuthorName = configMonoidAuthorName l <|> configMonoidAuthorName r
563+
, configMonoidAuthorEmail = configMonoidAuthorEmail l <|> configMonoidAuthorEmail r
564+
, configMonoidScmInit = configMonoidScmInit l <|> configMonoidScmInit r
547565
}
548566

549567
instance FromJSON (ConfigMonoid, [JSONWarning]) where
@@ -574,6 +592,9 @@ parseConfigMonoidJSON obj = do
574592
configMonoidConcurrentTests <- obj ..:? "concurrent-tests"
575593
configMonoidLocalBinPath <- obj ..:? "local-bin-path"
576594
configMonoidImageOpts <- jsonSubWarnings (obj ..:? "image" ..!= mempty)
595+
configMonoidAuthorName <- obj ..:? authorNameKey
596+
configMonoidAuthorEmail <- obj ..:? authorEmailKey
597+
configMonoidScmInit <- obj ..:? scmInitKey
577598
return ConfigMonoid {..}
578599

579600
-- | Newtype for non-orphan FromJSON instance.
@@ -849,3 +870,29 @@ packageEntryCurrDir = PackageEntry
849870
, peLocation = PLFilePath "."
850871
, peSubdirs = []
851872
}
873+
874+
-- | A software control system.
875+
data SCM = Git
876+
deriving (Show)
877+
878+
instance FromJSON SCM where
879+
parseJSON v = do
880+
s <- parseJSON v
881+
case s of
882+
"git" -> return Git
883+
_ -> fail ("Unknown or unsupported SCM: " <> s)
884+
885+
instance ToJSON SCM where
886+
toJSON Git = toJSON ("git" :: Text)
887+
888+
-- | Key used for the YAML file and templates.
889+
authorEmailKey :: Text
890+
authorEmailKey = "author-email"
891+
892+
-- | Key used for the YAML file and templates.
893+
authorNameKey :: Text
894+
authorNameKey = "author-name"
895+
896+
-- | Key used for the YAML file and templates.
897+
scmInitKey :: Text
898+
scmInitKey = "scm-init"

src/System/Process/Run.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
module System.Process.Run
1212
(runIn
1313
,callProcess
14-
,callProcess')
14+
,callProcess'
15+
,ProcessExitedUnsuccessfully)
1516
where
1617

1718
import Control.Exception.Lifted

0 commit comments

Comments
 (0)