diff --git a/.travis.yml b/.travis.yml index bac77556..90378e8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,9 @@ language: haskell install: - cabal update - - cabal install mega-sdist hspec cabal-meta cabal-src - - git clone https://github.com/snoyberg/tagstream-conduit.git - - cd tagstream-conduit - - cabal-src-install --src-only - - cd .. - - cabal-meta install --force-reinstalls --enable-tests + - cabal install --force-reinstalls mega-sdist hspec cabal-meta cabal-src + - cabal-meta install --force-reinstalls script: - echo Done + - mega-sdist --test diff --git a/README.md b/README.md index afceadd7..7536fb5a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ An advanced web framework using the Haskell programming language. Featuring: * techniques for constant-space memory consumption * asynchronous IO * this is built in to the Haskell programming language (like Erlang) - * handles a greater concurrent load than any other web application server # Learn more: http://yesodweb.com/ @@ -27,18 +26,19 @@ Your application is a cabal package and you use `cabal` to install its dependenc Install conflicts are unfortunately common in Haskell development. If you are not using any sandbox tools, you may discover that some of the other haskell installs on your system are broken. -You can prevent this by using sandbox tools: `cabal-dev` or `hsenv`. +You can prevent this by using cabal sandbox. -Isolating an entire project with a virtual machine is also a great idea, you just need some tools to help that process. -[Vagrant](http://vagrantup.com) is a great tool for that and there is a [Haskell Platform installer](https://bitbucket.org/puffnfresh/vagrant-haskell-heroku) for it. +Isolating an entire project is also a great idea, you just need some tools to help that process. +On Linux you can use Docker. +On any OS you can use a virtual machine. [Vagrant](http://vagrantup.com) is a great tool for that and there is a [Haskell Platform installer](https://bitbucket.org/puffnfresh/vagrant-haskell-heroku) for it. -## Using cabal-dev +## Using cabal sandbox -cabal-dev creates a sandboxed environment for an individual cabal package. -Instead of using the `cabal` command, use the `cabal-dev` command which will use the sandbox. +To sandbox a project, type: -Use `yesod devel --dev` when developing your application. + cabal sandbox init +This ensures that future installs will be local to the sandboxed directory. ## Installing the latest development version from github for use with your application @@ -55,7 +55,7 @@ In your application folder, create a `sources.txt` file with the following conte https://github.com/yesodweb/wai `./` means build your app. The yesod repos will be cloned and placed in a `vendor` repo. -Now run: `cabal-meta install`. If you use `cabal-dev`, run `cabal-meta --dev install` +Now run: `cabal-meta install`. This should work almost all of the time. You can read more on [cabal-meta](https://github.com/yesodweb/cabal-meta) If you aren't building from an application, remove the `./` and create a new directory for your sources.txt first. @@ -64,23 +64,9 @@ If you aren't building from an application, remove the `./` and create a new dir ## hsenv (Linux and Mac OS X) -[hsenv](https://github.com/tmhedberg/hsenv) prevents your custom build of Yesod from interfering with your currently installed cabal packages: +[hsenv](https://github.com/tmhedberg/hsenv) also provides a sandbox, but works at the shell level. +Generally we recommend using cabal sandbox, but hsenv has tools for allowing you to use different versions of GHC, which may be useful for you. -* hsenv creates an isolated environment like cabal-dev -* hsenv works at the shell level, so every shell must activate the hsenv -* cabal-dev by default isolates a single cabal package, but hsenv isolates multiple packages together. -* cabal-dev can isolate multiple packages together by using the -s sandbox argument - - -## cabal-src - -The cabal-src tool helps resolve dependency conflicts when installing local packages. -This capability is already built in if you are using cabal-dev or cabal-meta. Otherwise install cabal-src with: - - cabal install cabal-src - -Whenever you would use `cabal install` to install a local package, use `cabal-src-install` instead. -Our installer script now uses cabal-src-install when it is available. ## Cloning the repos @@ -100,7 +86,7 @@ done ## Building your changes to Yesod -Yesod is composed of 4 "mega-repos", each with multiple cabal packages. `./script/install` will run tests against each package and install each package. +The traditional Yesod stack requires 4 "mega-repos", each with multiple cabal packages. `./script/install` will run tests against each package and install each package. ### install package in all repos diff --git a/yesod-bin/GhcBuild.hs b/yesod-bin/GhcBuild.hs index 38913eab..9a1e81f6 100644 --- a/yesod-bin/GhcBuild.hs +++ b/yesod-bin/GhcBuild.hs @@ -39,7 +39,7 @@ import GHC.Paths (libdir) import HscTypes (HscEnv (..), emptyHomePackageTable) import qualified Module import MonadUtils (liftIO) -import Panic (ghcError, panic) +import Panic (throwGhcException, panic) import SrcLoc (Located, mkGeneralLocated) import qualified StaticFlags import StaticFlags (v_Ld_inputs) @@ -234,7 +234,7 @@ parseModeFlags args = do Nothing -> doMakeMode Just (m, _) -> m errs = errs1 ++ map (mkGeneralLocated "on the commandline") errs2 - when (not (null errs)) $ ghcError $ errorsToGhcException errs + when (not (null errs)) $ throwGhcException $ errorsToGhcException errs return (mode, flags' ++ leftover, warns) type ModeM = CmdLineP (Maybe (Mode, String), [String], [Located String]) diff --git a/yesod-bin/Options.hs b/yesod-bin/Options.hs index 25b3d940..c180f31b 100644 --- a/yesod-bin/Options.hs +++ b/yesod-bin/Options.hs @@ -71,7 +71,7 @@ injectDefaultP env path p@(OptP o) in parseri { infoParser = injectDefaultP env (path ++ [normalizeName cmd]) (infoParser parseri) } in OptP (Option (CmdReader cmds (`M.lookup` cmdMap)) props) | (Option (OptReader names (CReader _ rdr) _) _) <- o = - p <|> either (const empty) pure (msum $ map (rdr <=< (maybe (Left $ ErrorMsg "Missing environment variable") Right . getEnvValue env path)) names) + p <|> either' (const empty) pure (msum $ map (rdr <=< (maybe (left $ ErrorMsg "Missing environment variable") right . getEnvValue env path)) names) | (Option (FlagReader names a) _) <- o = p <|> if any ((==Just "1") . getEnvValue env path) names then pure a else empty | otherwise = p @@ -81,6 +81,16 @@ injectDefaultP env path (AltP p1 p2) = AltP (injectDefaultP env path p1) (injectDefaultP env path p2) injectDefaultP _env _path b@(BindP {}) = b +#if MIN_VERSION_optparse_applicative(0,6,0) +right = ReadM . Right +left = ReadM . Left +either' f g (ReadM x) = either f g x +#else +right = Right +left = Left +either' = either +#endif + getEnvValue :: M.Map [String] String -> [String] -> OptName -> Maybe String getEnvValue env path (OptLong l) = M.lookup (path ++ [normalizeName l]) env getEnvValue _ _ _ = Nothing diff --git a/yesod-bin/input/done.cg b/yesod-bin/input/done.cg index b838c2ea..280f3af4 100644 --- a/yesod-bin/input/done.cg +++ b/yesod-bin/input/done.cg @@ -24,9 +24,4 @@ Take part in the community: http://yesodweb.com/page/community Start your project: - cd PROJECTNAME && cabal install && yesod devel - -or if you use cabal-dev: - - cd PROJECTNAME && cabal-dev install && yesod --dev devel - + cd PROJECTNAME && cabal sandbox init && cabal install && yesod devel diff --git a/yesod-bin/main.hs b/yesod-bin/main.hs index 3c5ff739..f0f4e4b0 100755 --- a/yesod-bin/main.hs +++ b/yesod-bin/main.hs @@ -16,6 +16,9 @@ import qualified Paths_yesod_bin import Scaffolding.Scaffolder import Options.Applicative.Builder.Internal (Mod, OptionFields) +#if MIN_VERSION_optparse_applicative(0,6,0) +import Options.Applicative.Types (ReadM (ReadM)) +#endif #ifndef WINDOWS import Build (touch) @@ -165,7 +168,11 @@ optStr :: Mod OptionFields (Maybe String) -> Parser (Maybe String) optStr m = nullOption $ value Nothing <> reader (success . str) <> m where +#if MIN_VERSION_optparse_applicative(0,6,0) + success = ReadM . Right +#else success = Right +#endif -- | Like @rawSystem@, but exits if it receives a non-success result. rawSystem' :: String -> [String] -> IO () diff --git a/yesod-bin/yesod-bin.cabal b/yesod-bin/yesod-bin.cabal index cc27d0f1..27110e13 100644 --- a/yesod-bin/yesod-bin.cabal +++ b/yesod-bin/yesod-bin.cabal @@ -1,5 +1,5 @@ name: yesod-bin -version: 1.2.3.3 +version: 1.2.4 license: MIT license-file: LICENSE author: Michael Snoyman diff --git a/yesod-core/Yesod/Core/Widget.hs b/yesod-core/Yesod/Core/Widget.hs index be977649..a972efad 100644 --- a/yesod-core/Yesod/Core/Widget.hs +++ b/yesod-core/Yesod/Core/Widget.hs @@ -47,6 +47,7 @@ module Yesod.Core.Widget , handlerToWidget -- * Internal , whamletFileWithSettings + , asWidgetT ) where import Data.Monoid diff --git a/yesod-core/yesod-core.cabal b/yesod-core/yesod-core.cabal index edf6f15e..1c158074 100644 --- a/yesod-core/yesod-core.cabal +++ b/yesod-core/yesod-core.cabal @@ -1,5 +1,5 @@ name: yesod-core -version: 1.2.4.3 +version: 1.2.5 license: MIT license-file: LICENSE author: Michael Snoyman @@ -41,7 +41,7 @@ library , transformers >= 0.2.2 && < 0.4 , clientsession >= 0.9 && < 0.10 , random >= 1.0.0.2 && < 1.1 - , cereal >= 0.3 && < 0.4 + , cereal >= 0.3 , old-locale >= 1.0.0.2 && < 1.1 , failure >= 0.2 && < 0.3 , containers >= 0.2 @@ -91,6 +91,9 @@ library -- This looks like a GHC bug extensions: MultiParamTypeClasses + -- Workaround for: http://ghc.haskell.org/trac/ghc/ticket/8443 + extensions: TemplateHaskell + test-suite tests type: exitcode-stdio-1.0 main-is: test.hs @@ -118,6 +121,7 @@ test-suite tests , lifted-base , resourcet ghc-options: -Wall + extensions: TemplateHaskell source-repository head type: git diff --git a/yesod-form/Yesod/Form/Fields.hs b/yesod-form/Yesod/Form/Fields.hs index 5c16d7eb..0689859f 100644 --- a/yesod-form/Yesod/Form/Fields.hs +++ b/yesod-form/Yesod/Form/Fields.hs @@ -36,6 +36,8 @@ module Yesod.Form.Fields , selectFieldList , radioField , radioFieldList + , checkboxesFieldList + , checkboxesField , multiSelectField , multiSelectFieldList , Option (..) @@ -62,8 +64,8 @@ import qualified Text.Email.Validate as Email import Data.Text.Encoding (encodeUtf8, decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) import Network.URI (parseURI) -import Database.Persist.Sql (PersistField, PersistFieldSql) -import Database.Persist (Entity (..)) +import Database.Persist.Sql (PersistField, PersistFieldSql (..)) +import Database.Persist (Entity (..), SqlType (SqlString)) import Text.HTML.SanitizeXSS (sanitizeBalance) import Control.Monad (when, unless) import Data.Maybe (listToMaybe, fromMaybe) @@ -166,7 +168,9 @@ $newline never -- | A newtype wrapper around a 'Text' that converts newlines to HTML -- br-tags. newtype Textarea = Textarea { unTextarea :: Text } - deriving (Show, Read, Eq, PersistField, PersistFieldSql, Ord) + deriving (Show, Read, Eq, PersistField, Ord) +instance PersistFieldSql Textarea where + sqlType _ = SqlString instance ToHtml Textarea where toHtml = unsafeByteString @@ -388,6 +392,28 @@ radioFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg) -> Field (HandlerT site IO) a radioFieldList = radioField . optionsPairs +checkboxesFieldList :: (Eq a, RenderMessage site FormMessage, RenderMessage site msg) => [(msg, a)] + -> Field (HandlerT site IO) [a] +checkboxesFieldList = checkboxesField . optionsPairs + +checkboxesField :: (Eq a, RenderMessage site FormMessage) + => HandlerT site IO (OptionList a) + -> Field (HandlerT site IO) [a] +checkboxesField ioptlist = (multiSelectField ioptlist) + { fieldView = + \theId name attrs val isReq -> do + opts <- fmap olOptions $ handlerToWidget ioptlist + let optselected (Left _) _ = False + optselected (Right vals) opt = (optionInternalValue opt) `elem` vals + [whamlet| + + $forall opt <- opts +