diff --git a/ChangeLog.md b/ChangeLog.md index 5b5d356942..0b3772d5c2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,7 @@ ## Unreleased * Fall back to cabal dependency solver when a snapshot can't be found +* Basic implementation of `stack new` [#137](https://github.com/commercialhaskell/stack/issues/137) ## 0.0.3 diff --git a/new-template/LICENSE b/new-template/LICENSE new file mode 100644 index 0000000000..c304a94836 --- /dev/null +++ b/new-template/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2015 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Your name here nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/new-template/Setup.hs b/new-template/Setup.hs new file mode 100644 index 0000000000..9a994af677 --- /dev/null +++ b/new-template/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/new-template/app/Main.hs b/new-template/app/Main.hs new file mode 100644 index 0000000000..de1c1ab35c --- /dev/null +++ b/new-template/app/Main.hs @@ -0,0 +1,6 @@ +module Main where + +import Lib + +main :: IO () +main = someFunc diff --git a/new-template/new-template.cabal b/new-template/new-template.cabal new file mode 100644 index 0000000000..0eaed79c53 --- /dev/null +++ b/new-template/new-template.cabal @@ -0,0 +1,41 @@ +name: new-template +version: 0.1.0.0 +synopsis: Initial project template from stack +description: Please see README.md +homepage: http://github.com/name/project +license: BSD3 +license-file: LICENSE +author: Your name here +maintainer: your.address@example.com +-- copyright: +category: Web +build-type: Simple +-- extra-source-files: +cabal-version: >=1.10 + +library + hs-source-dirs: src + exposed-modules: Lib + build-depends: base >= 4.7 && < 5 + default-language: Haskell2010 + +executable new-template-exe + hs-source-dirs: app + main-is: Main.hs + ghc-options: -threaded -rtsopts -with-rtsopts=-N + build-depends: base + , new-template + default-language: Haskell2010 + +test-suite new-template-test + type: exitcode-stdio-1.0 + hs-source-dirs: test + main-is: Spec.hs + build-depends: base + , new-template + ghc-options: -threaded -rtsopts -with-rtsopts=-N + default-language: Haskell2010 + +source-repository head + type: git + location: https://github.com/name/project diff --git a/new-template/src/Lib.hs b/new-template/src/Lib.hs new file mode 100644 index 0000000000..d36ff2714d --- /dev/null +++ b/new-template/src/Lib.hs @@ -0,0 +1,6 @@ +module Lib + ( someFunc + ) where + +someFunc :: IO () +someFunc = putStrLn "someFunc" diff --git a/new-template/test/Spec.hs b/new-template/test/Spec.hs new file mode 100644 index 0000000000..cd4753fc9c --- /dev/null +++ b/new-template/test/Spec.hs @@ -0,0 +1,2 @@ +main :: IO () +main = putStrLn "Test suite not yet implemented" diff --git a/src/Stack/New.hs b/src/Stack/New.hs index 8d9547645b..cfd173661c 100644 --- a/src/Stack/New.hs +++ b/src/Stack/New.hs @@ -1,8 +1,42 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} module Stack.New ( newProject ) where -import Control.Monad.IO.Class +import Control.Monad (filterM, forM_, unless) +import Control.Monad.IO.Class (MonadIO, liftIO) +import Control.Monad.Logger (MonadLogger, logInfo) +import Data.ByteString (ByteString) +import qualified Data.ByteString as S +import Data.FileEmbed (embedDir) +import Data.Map (Map) +import qualified Data.Map as Map +import qualified Data.Text as T +import System.Directory (createDirectoryIfMissing, + doesFileExist) +import System.FilePath (takeDirectory) -newProject :: MonadIO m => m () -newProject = error "new command not yet implemented, check out https://github.com/commercialhaskell/stack/issues/137 for status and to get involved" +newProject :: (MonadIO m, MonadLogger m) + => m () +newProject = do + $logInfo "NOTE: Currently stack new functionality is very rudimentary" + $logInfo "There are plans to make this feature more useful in the future" + $logInfo "For more information, see: https://github.com/commercialhaskell/stack/issues/137" + $logInfo "For now, we'll just be generating a basic project structure in your current directory" + + exist <- filterM (liftIO . doesFileExist) (Map.keys files) + unless (null exist) $ + error $ unlines + $ "The following files already exist, refusing to overwrite:" + : map ("- " ++) exist + + $logInfo "" + forM_ (Map.toList files) $ \(fp, bs) -> do + $logInfo $ T.pack $ "Writing: " ++ fp + liftIO $ do + createDirectoryIfMissing True $ takeDirectory fp + S.writeFile fp bs + +files :: Map FilePath ByteString +files = Map.fromList $(embedDir "new-template") diff --git a/src/main/Main.hs b/src/main/Main.hs index aea3fc41fd..fca813210b 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -96,8 +96,8 @@ main = buildOpts addCommand "new" "Create a brand new project" - (\_ _ -> newProject) - (pure ()) + newCmd + initOptsParser addCommand "init" "Initialize a stack project based on one or more cabal packages" initCmd @@ -610,3 +610,13 @@ initCmd initOpts go@GlobalOpts{..} = do Docker.rerunWithOptionalContainer (lcConfig lc) (lcProjectRoot lc) $ runStackT manager globalLogLevel (lcConfig lc) globalTerminal $ initProject globalResolver initOpts + +-- | Project creation +newCmd :: InitOpts -> GlobalOpts -> IO () +newCmd initOpts go@GlobalOpts{..} = do + (manager,lc) <- loadConfigWithOpts go + runStackLoggingT manager globalLogLevel globalTerminal $ + Docker.rerunWithOptionalContainer (lcConfig lc) (lcProjectRoot lc) $ + runStackT manager globalLogLevel (lcConfig lc) globalTerminal $ do + newProject + initProject globalResolver initOpts diff --git a/stack.cabal b/stack.cabal index 9c8f6eb6b4..fb350b7b2e 100644 --- a/stack.cabal +++ b/stack.cabal @@ -13,8 +13,8 @@ maintainer: chrisdone@fpcomplete.com category: Development build-type: Simple cabal-version: >=1.10 -extra-source-files: README.md ChangeLog.md homepage: https://github.com/commercialhaskell/stack +extra-source-files: README.md ChangeLog.md -- Glob would be nice, but apparently Cabal doesn't support it: -- cabal: filepath wildcard 'test/package-dump/*.txt' does not match any files. @@ -22,6 +22,13 @@ homepage: https://github.com/commercialhaskell/stack test/package-dump/ghc-7.8.txt test/package-dump/ghc-7.10.txt + new-template/src/Lib.hs + new-template/new-template.cabal + new-template/test/Spec.hs + new-template/app/Main.hs + new-template/LICENSE + new-template/Setup.hs + library hs-source-dirs: src/ ghc-options: -Wall @@ -136,6 +143,7 @@ library , yaml >= 0.8.10.1 , zlib >= 0.5.4.2 , deepseq + , file-embed if !os(windows) build-depends: unix >= 2.7.0.1 default-language: Haskell2010