From acf09608806c3f7744785eb3d0bc74e801f16901 Mon Sep 17 00:00:00 2001 From: Adam Bergmark Date: Fri, 2 Oct 2015 20:35:32 +0200 Subject: [PATCH 001/106] Update travis instructions to use stack-0.1.5.0 --- doc/GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/GUIDE.md b/doc/GUIDE.md index 589239e8a3..65ed968fa2 100644 --- a/doc/GUIDE.md +++ b/doc/GUIDE.md @@ -1603,7 +1603,7 @@ before_install: # Download and unpack the stack executable - mkdir -p ~/.local/bin - export PATH=$HOME/.local/bin:$PATH -- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.4.0/stack-0.1.4.0-x86_64-linux.tar.gz | tar xz -C ~/.local/bin +- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.5.0/stack-0.1.5.0-x86_64-linux.tar.gz | tar xz -C ~/.local/bin # This line does all of the work: installs GHC if necessary, build the library, # executables, and test suites, and runs the test suites. --no-terminal works From 3e9b1a823de69bdb1c81fa667d5e9905405401d7 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 12 Oct 2015 11:26:15 -0700 Subject: [PATCH 002/106] Add support for old GHCJS unpack dir for booting #749 --- src/Stack/Setup.hs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index 0efd24faf1..52e779a451 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -898,7 +898,26 @@ ensureGhcjsBooted menv cv shouldBoot = do if not shouldBoot then throwM GHCJSNotBooted else do config <- asks getConfig destDir <- installDir (configLocalPrograms config) (ToolGhcjs cv) - bootGhcjs menv (destDir $(mkRelFile "src/stack.yaml")) + let stackYaml = destDir $(mkRelFile "src/stack.yaml") + -- TODO: Remove 'actualStackYaml' and just use + -- 'stackYaml' for a version after 0.1.6. It's for + -- compatibility with the directories setup used for + -- most of the life of the development branch between + -- 0.1.5 and 0.1.6. See + -- https://github.com/commercialhaskell/stack/issues/749#issuecomment-147382783 + -- This only affects the case where GHCJS has been + -- installed with an older version and not yet booted. + stackYamlExists <- fileExists stackYaml + actualStackYaml <- if stackYamlExists then return stackYaml + else case cv of + GhcjsVersion version _ -> + liftM ((destDir Path. $(mkRelDir "src")) Path.) $ + parseRelFile $ "ghcjs-" ++ versionString version ++ "/stack.yaml" + _ -> fail "ensureGhcjsBooted invoked on non GhcjsVersion" + actualStackYamlExists <- fileExists actualStackYaml + when (not actualStackYamlExists) $ + fail "Couldn't find GHCJS stack.yaml in old or new location." + bootGhcjs menv actualStackYaml Left err -> throwM err bootGhcjs :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) From 6a9261fccd7f205e2c6e5eea4227fdca32681802 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sun, 11 Oct 2015 13:45:40 -0700 Subject: [PATCH 003/106] fix: a docker section in global/user config caused 'stack new' to try to start a container --- src/Stack/Config.hs | 8 +++++++- src/Stack/Config/Docker.hs | 2 +- src/Stack/Options.hs | 2 +- src/Stack/Types/Docker.hs | 10 +++++----- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs index 8ffb29fb67..0ddd3e45ab 100644 --- a/src/Stack/Config.hs +++ b/src/Stack/Config.hs @@ -268,7 +268,13 @@ loadConfig :: (MonadLogger m,MonadIO m,MonadCatch m,MonadThrow m,MonadBaseContro loadConfig configArgs mstackYaml = do stackRoot <- determineStackRoot userConfigPath <- getDefaultUserConfigPath stackRoot - extraConfigs <- getExtraConfigs userConfigPath >>= mapM loadYaml + extraConfigs0 <- getExtraConfigs userConfigPath >>= mapM loadYaml + let extraConfigs = + -- non-project config files' existence of a docker section should never default docker + -- to enabled, so make it look like they didn't exist + map (\c -> c {configMonoidDockerOpts = + (configMonoidDockerOpts c) {dockerMonoidDefaultEnable = False}}) + extraConfigs0 mproject <- loadProjectConfig mstackYaml config <- configFromConfigMonoid stackRoot userConfigPath (fmap (\(proj, _, _) -> proj) mproject) $ mconcat $ case mproject of diff --git a/src/Stack/Config/Docker.hs b/src/Stack/Config/Docker.hs index 00669a5d64..53d40dabf4 100644 --- a/src/Stack/Config/Docker.hs +++ b/src/Stack/Config/Docker.hs @@ -19,7 +19,7 @@ dockerOptsFromMonoid => Maybe Project -> Path Abs Dir -> DockerOptsMonoid -> m DockerOpts dockerOptsFromMonoid mproject stackRoot DockerOptsMonoid{..} = do let dockerEnable = - fromMaybe (fromMaybe False dockerMonoidExists) dockerMonoidEnable + fromMaybe dockerMonoidDefaultEnable dockerMonoidEnable dockerImage = let defaultTag = case mproject of diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 5cf7bf1dda..dfde5c72fa 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -293,7 +293,7 @@ configOptsParser docker = dockerOptsParser :: Bool -> Parser DockerOptsMonoid dockerOptsParser showOptions = DockerOptsMonoid - <$> pure Nothing + <$> pure False <*> maybeBoolFlags dockerCmdName "using a Docker container" hide diff --git a/src/Stack/Types/Docker.hs b/src/Stack/Types/Docker.hs index e97a4c08e9..82a1d0559c 100644 --- a/src/Stack/Types/Docker.hs +++ b/src/Stack/Types/Docker.hs @@ -52,8 +52,8 @@ data DockerOpts = DockerOpts -- | An uninterpreted representation of docker options. -- Configurations may be "cascaded" using mappend (left-biased). data DockerOptsMonoid = DockerOptsMonoid - {dockerMonoidExists :: !(Maybe Bool) - -- ^ Does a @docker:@ section exist in the top-level (usually project) config? + {dockerMonoidDefaultEnable :: !Bool + -- ^ Should Docker be defaulted to enabled (does @docker:@ section exist in the config)? ,dockerMonoidEnable :: !(Maybe Bool) -- ^ Is using Docker enabled? ,dockerMonoidRepoOrImage :: !(Maybe DockerMonoidRepoOrImage) @@ -92,7 +92,7 @@ data DockerOptsMonoid = DockerOptsMonoid -- | Decode uninterpreted docker options from JSON/YAML. instance FromJSON (DockerOptsMonoid, [JSONWarning]) where parseJSON = withObjectWarnings "DockerOptsMonoid" - (\o -> do dockerMonoidExists <- pure (Just True) + (\o -> do dockerMonoidDefaultEnable <- pure True dockerMonoidEnable <- o ..:? dockerEnableArgName dockerMonoidRepoOrImage <- ((Just . DockerMonoidImage) <$> o ..: dockerImageArgName) <|> ((Just . DockerMonoidRepo) <$> o ..: dockerRepoArgName) <|> @@ -115,7 +115,7 @@ instance FromJSON (DockerOptsMonoid, [JSONWarning]) where -- | Left-biased combine Docker options instance Monoid DockerOptsMonoid where mempty = DockerOptsMonoid - {dockerMonoidExists = Just False + {dockerMonoidDefaultEnable = False ,dockerMonoidEnable = Nothing ,dockerMonoidRepoOrImage = Nothing ,dockerMonoidRegistryLogin = Nothing @@ -133,7 +133,7 @@ instance Monoid DockerOptsMonoid where ,dockerMonoidSetUser = Nothing } mappend l r = DockerOptsMonoid - {dockerMonoidExists = dockerMonoidExists l <|> dockerMonoidExists r + {dockerMonoidDefaultEnable = dockerMonoidDefaultEnable l || dockerMonoidDefaultEnable r ,dockerMonoidEnable = dockerMonoidEnable l <|> dockerMonoidEnable r ,dockerMonoidRepoOrImage = dockerMonoidRepoOrImage l <|> dockerMonoidRepoOrImage r ,dockerMonoidRegistryLogin = dockerMonoidRegistryLogin l <|> dockerMonoidRegistryLogin r From b483f71eb2313afd777764241dbe3bd232809952 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 12 Oct 2015 20:49:46 -0700 Subject: [PATCH 004/106] Add ChangeLog note about unified coverage report --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index 7cd8bdb2fa..54c145ad15 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -31,6 +31,7 @@ Other enhancements: * Docker: when Docker Engine is remote, don't run containerized processes as host's UID/GID [#194](https://github.com/commercialhaskell/stack/issues/194) * Docker: `set-user` option to enable/disable running containerized processes as host's UID/GID [#194](https://github.com/commercialhaskell/stack/issues/194) * Custom Setup.hs files are now precompiled instead of interpreted. This should be a major performance win for certain edge cases (biggest example: [building Cabal itself](https://github.com/commercialhaskell/stack/issues/1041)) while being either neutral or a minor slowdown for more common cases. +* `stack test --coverage` now also generates a unified coverage report for multiple test-suites / packages. In the unified report, test-suites can contribute to the coverage of other packages. Bug fixes: From 8f3961fd5af2eb982125a000d05adc988348dbc8 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 20:59:29 -0700 Subject: [PATCH 005/106] Bump version to 0.1.7.0 --- ChangeLog.md | 3 +++ stack.cabal | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 54c145ad15..0772ceb89b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,8 @@ ## Unreleased changes + +## v0.1.6.0 + Major changes: * "stack setup" now supports building and booting GHCJS from source tarball. diff --git a/stack.cabal b/stack.cabal index 7772b525f4..216b537614 100644 --- a/stack.cabal +++ b/stack.cabal @@ -1,5 +1,5 @@ name: stack -version: 0.1.5.1 +version: 0.1.7.0 synopsis: The Haskell Tool Stack description: Please see the README.md for usage information, and the wiki on Github for more details. Also, note that From e263281d3479505065e269ad0bf353cdbcb401ba Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 21:20:42 -0700 Subject: [PATCH 006/106] Bump version to 0.1.6.0 --- ChangeLog.md | 3 +++ stack.cabal | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 54c145ad15..0772ceb89b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,8 @@ ## Unreleased changes + +## v0.1.6.0 + Major changes: * "stack setup" now supports building and booting GHCJS from source tarball. diff --git a/stack.cabal b/stack.cabal index 7772b525f4..c332472d86 100644 --- a/stack.cabal +++ b/stack.cabal @@ -1,5 +1,5 @@ name: stack -version: 0.1.5.1 +version: 0.1.6.0 synopsis: The Haskell Tool Stack description: Please see the README.md for usage information, and the wiki on Github for more details. Also, note that From c8bb25951cd88df1675e58fe9b574e02eabddb1e Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 21:21:34 -0700 Subject: [PATCH 007/106] release.hs: swap OS and architecture in bindist filenames for better sorting in Github release --- etc/scripts/release.hs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/etc/scripts/release.hs b/etc/scripts/release.hs index 15d80b84a9..21d063187c 100755 --- a/etc/scripts/release.hs +++ b/etc/scripts/release.hs @@ -558,7 +558,7 @@ buildDockerImage buildDir imageTag out = do writeFileChanged out imageIdOut return (trim imageIdOut) --- | Name of the release binary (e.g. @stack-x.y.x-arch-os[-variant]@) +-- | Name of the release binary (e.g. @stack-x.y.x-os-arch[-variant]@) binaryName :: Global -> String binaryName global@Global{..} = concat @@ -566,7 +566,9 @@ binaryName global@Global{..} = , "-" , stackVersionStr global , "-" - , platformName global + , display platformOS + , "-" + , display gArch , if null gBinarySuffix then "" else "-" ++ gBinarySuffix ] -- | String representation of stack package version. @@ -574,11 +576,6 @@ stackVersionStr :: Global -> String stackVersionStr = display . pkgVersion . package . gStackPackageDescription --- | Name of current platform. -platformName :: Global -> String -platformName Global{..} = - display (Platform gArch platformOS) - -- | Current operating system. platformOS :: OS platformOS = From ad4a36f19d27827bcba857cd8cf4aabd17e67f27 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 21:21:58 -0700 Subject: [PATCH 008/106] stack.cabal: add Markdown docs to extra-source-files --- stack.cabal | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/stack.cabal b/stack.cabal index c332472d86..a8c6a02c4b 100644 --- a/stack.cabal +++ b/stack.cabal @@ -14,7 +14,21 @@ category: Development build-type: Simple cabal-version: >=1.10 homepage: https://github.com/commercialhaskell/stack -extra-source-files: README.md ChangeLog.md +extra-source-files: README.md + ChangeLog.md + CONTRIBUTING.md + doc/GUIDE.md + doc/build_command.md + doc/install_and_upgrade.md + doc/MAINTAINER_GUIDE.md + doc/dependency_visualization.md + doc/nonstandard_project_init.md + doc/SIGNING_KEY.md + doc/docker_integration.md + doc/shell_autocompletion.md + doc/architecture.md + doc/faq.md + doc/yaml_configuration.md -- Glob would be nice, but apparently Cabal doesn't support it: -- cabal: filepath wildcard 'test/package-dump/*.txt' does not match any files. From 2b095d981bdb048a05b2a1c36676b7c99cf5156e Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 21:36:00 -0700 Subject: [PATCH 009/106] GUIDE.md: update travis command --- doc/GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/GUIDE.md b/doc/GUIDE.md index ed2415e43c..1b22b3de86 100644 --- a/doc/GUIDE.md +++ b/doc/GUIDE.md @@ -1603,7 +1603,7 @@ before_install: # Download and unpack the stack executable - mkdir -p ~/.local/bin - export PATH=$HOME/.local/bin:$PATH -- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.4.0/stack-0.1.4.0-x86_64-linux.tar.gz | tar xz -C ~/.local/bin +- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.6.0/stack-0.1.6.0-linux-x86_64.tar.gz | tar xz --strip-components=1 -C ~/.local/bin '*/stack' # This line does all of the work: installs GHC if necessary, build the library, # executables, and test suites, and runs the test suites. --no-terminal works From b777856765d72ce61c0b9fb396beb1bcdab381ff Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 21:55:38 -0700 Subject: [PATCH 010/106] Fix build warning on Windows --- src/Stack/Build.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Stack/Build.hs b/src/Stack/Build.hs index fc6cb14cee..a760ec68f9 100644 --- a/src/Stack/Build.hs +++ b/src/Stack/Build.hs @@ -61,7 +61,6 @@ import System.FileLock (FileLock, unlockFile) #ifdef WINDOWS import System.Win32.Console (setConsoleCP, setConsoleOutputCP, getConsoleCP, getConsoleOutputCP) import qualified Control.Monad.Catch as Catch -import qualified Data.Text as T #endif type M env m = (MonadIO m,MonadReader env m,HasHttpManager env,HasBuildConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,MonadMask m,HasLogLevel env,HasEnvConfig env,HasTerminal env) From 40429908679674023a2f900ebbe2e4d56daea5b9 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 22:12:01 -0700 Subject: [PATCH 011/106] Fix resolver in 796-ghc-options integration test --- test/integration/tests/796-ghc-options/files/stack.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/tests/796-ghc-options/files/stack.yaml b/test/integration/tests/796-ghc-options/files/stack.yaml index 7d23a0eb48..0a78d1258d 100644 --- a/test/integration/tests/796-ghc-options/files/stack.yaml +++ b/test/integration/tests/796-ghc-options/files/stack.yaml @@ -1,4 +1,4 @@ -resolver: ghc-7 +resolver: ghc-7.10 ghc-options: "*": -DFOO ghc-options: -DBAR From 0123b0ad4e685d10b159c1100428777791e3c4c7 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Mon, 12 Oct 2015 22:19:49 -0700 Subject: [PATCH 012/106] release.hs: fix warning --- etc/scripts/release.hs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/etc/scripts/release.hs b/etc/scripts/release.hs index 21d063187c..9f99df4a0b 100755 --- a/etc/scripts/release.hs +++ b/etc/scripts/release.hs @@ -549,15 +549,6 @@ dropDirectoryPrefix prefix path = Nothing -> error ("dropDirectoryPrefix: cannot drop " ++ show prefix ++ " from " ++ show path) Just stripped -> stripped --- | Build a Docker image and write its ID to a file if changed. -buildDockerImage :: FilePath -> String -> FilePath -> Action String -buildDockerImage buildDir imageTag out = do - alwaysRerun - () <- cmd "docker build" ["--tag=" ++ imageTag, buildDir] - (Stdout imageIdOut) <- cmd "docker inspect --format={{.Id}}" [imageTag] - writeFileChanged out imageIdOut - return (trim imageIdOut) - -- | Name of the release binary (e.g. @stack-x.y.x-os-arch[-variant]@) binaryName :: Global -> String binaryName global@Global{..} = From 78f0c990635b0eb924fdaeca73329c749db90472 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Tue, 13 Oct 2015 06:27:56 +0000 Subject: [PATCH 013/106] Add the --fast option (turns off optimizations) --- ChangeLog.md | 1 + src/Stack/Options.hs | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0772ceb89b..4ac0a37d8d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -35,6 +35,7 @@ Other enhancements: * Docker: `set-user` option to enable/disable running containerized processes as host's UID/GID [#194](https://github.com/commercialhaskell/stack/issues/194) * Custom Setup.hs files are now precompiled instead of interpreted. This should be a major performance win for certain edge cases (biggest example: [building Cabal itself](https://github.com/commercialhaskell/stack/issues/1041)) while being either neutral or a minor slowdown for more common cases. * `stack test --coverage` now also generates a unified coverage report for multiple test-suites / packages. In the unified report, test-suites can contribute to the coverage of other packages. +* --fast turns off optimizations Bug fixes: diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index dfde5c72fa..a9bff6d6e7 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -117,10 +117,14 @@ buildOptsParser cmd = dryRun = flag False True (long "dry-run" <> help "Don't build anything, just prepare to") - ghcOpts = (++) + ghcOpts = (\x y z -> concat [x, y, z]) <$> flag [] ["-Wall", "-Werror"] ( long "pedantic" - <> help "Turn on -Wall and -Werror (note: option name may change in the future" + <> help "Turn on -Wall and -Werror" + ) + <*> flag [] ["-O0"] + ( long "fast" + <> help "Turn off optimizations (-O0)" ) <*> many (textOption (long "ghc-options" <> metavar "OPTION" <> From 5c2664c235e5da57dbfb7f3d7a821e00c4f1147c Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Tue, 13 Oct 2015 06:22:06 +0000 Subject: [PATCH 014/106] Remove ignore package dependency Pinging @agrafix. I believe that this is no longer necessary in Stack since the file-watch code only monitors files which are actually used by the build process. Can you confirm that this doesn't break your workflow? --- src/Stack/FileWatch.hs | 20 ++++---------------- src/main/Main.hs | 10 ++-------- stack.cabal | 1 - stack.yaml | 4 ---- 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/Stack/FileWatch.hs b/src/Stack/FileWatch.hs index a363f9a587..4ff071d084 100644 --- a/src/Stack/FileWatch.hs +++ b/src/Stack/FileWatch.hs @@ -21,7 +21,6 @@ import qualified Data.Set as Set import Data.String (fromString) import Data.Traversable (forM) import GHC.IO.Handle (hIsTerminalDevice) -import Ignore import Path import System.Console.ANSI import System.Exit @@ -33,13 +32,11 @@ printExceptionStderr :: Exception e => e -> IO () printExceptionStderr e = L.hPut stderr $ toLazyByteString $ fromShow e <> copyByteString "\n" -fileWatch :: IO (Path Abs Dir) - -> ((Set (Path Abs File) -> IO ()) -> IO ()) +fileWatch :: ((Set (Path Abs File) -> IO ()) -> IO ()) -> IO () fileWatch = fileWatchConf defaultConfig -fileWatchPoll :: IO (Path Abs Dir) - -> ((Set (Path Abs File) -> IO ()) -> IO ()) +fileWatchPoll :: ((Set (Path Abs File) -> IO ()) -> IO ()) -> IO () fileWatchPoll = fileWatchConf $ defaultConfig { confUsePolling = True } @@ -48,21 +45,12 @@ fileWatchPoll = fileWatchConf $ defaultConfig { confUsePolling = True } -- The action provided takes a callback that is used to set the files to be -- watched. When any of those files are changed, we rerun the action again. fileWatchConf :: WatchConfig - -> IO (Path Abs Dir) -> ((Set (Path Abs File) -> IO ()) -> IO ()) -> IO () -fileWatchConf cfg getProjectRoot inner = withManagerConf cfg $ \manager -> do +fileWatchConf cfg inner = withManagerConf cfg $ \manager -> do allFiles <- newTVarIO Set.empty dirtyVar <- newTVarIO True watchVar <- newTVarIO Map.empty - projRoot <- getProjectRoot - mChecker <- findIgnoreFiles [VCSGit, VCSMercurial, VCSDarcs] projRoot >>= buildChecker - (FileIgnoredChecker isFileIgnored) <- - case mChecker of - Left err -> - do putStrLn $ "Failed to parse VCS's ignore file: " ++ err - return $ FileIgnoredChecker (const False) - Right chk -> return chk let onChange event = atomically $ do files <- readTVar allFiles @@ -96,7 +84,7 @@ fileWatchConf cfg getProjectRoot inner = withManagerConf cfg $ \manager -> do return Nothing startListening = Map.mapWithKey $ \dir () -> do let dir' = fromString $ toFilePath dir - listen <- watchDir manager dir' (not . isFileIgnored . eventPath) onChange + listen <- watchDir manager dir' (const True) onChange return $ Just listen let watchInput = do diff --git a/src/main/Main.hs b/src/main/Main.hs index 30be5a8e5a..7fa8f18f41 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -701,18 +701,12 @@ buildCmd opts go = do hPutStrLn stderr "See: https://github.com/commercialhaskell/stack/issues/1015" error "-prof GHC option submitted" case boptsFileWatch opts of - FileWatchPoll -> fileWatchPoll getProjectRoot inner - FileWatch -> fileWatch getProjectRoot inner + FileWatchPoll -> fileWatchPoll inner + FileWatch -> fileWatch inner NoFileWatch -> inner $ const $ return () where inner setLocalFiles = withBuildConfigAndLock go $ \lk -> Stack.Build.build setLocalFiles lk opts - getProjectRoot = do - (manager, lc) <- loadConfigWithOpts go - bconfig <- - runStackLoggingTGlobal manager go $ - lcLoadBuildConfig lc (globalResolver go) - return (bcRoot bconfig) uninstallCmd :: [String] -> GlobalOpts -> IO () uninstallCmd _ go = withConfigAndLock go $ do diff --git a/stack.cabal b/stack.cabal index 216b537614..addabe75f8 100644 --- a/stack.cabal +++ b/stack.cabal @@ -139,7 +139,6 @@ library , http-client-tls >= 0.2.2 , http-conduit >= 2.1.7 , http-types >= 0.8.6 - , ignore >= 0.1.1 , lifted-base , monad-control , monad-logger >= 0.3.13.1 diff --git a/stack.yaml b/stack.yaml index b5a6b50fd2..a75523da6e 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,10 +1,6 @@ resolver: lts-3.7 extra-deps: -- ignore-0.1.1.0 - binary-tagged-0.1.1.0 -flags: - ignore: - without-pcre: true image: container: base: "fpco/ubuntu-with-libgmp:14.04" From 35d043edee4b6a5d616061fa9623ca9ffcd421f1 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Tue, 13 Oct 2015 13:28:36 -0700 Subject: [PATCH 015/106] release.hs: build rather than interpreting, use 'stack --local-bin-dir install' instead of using the build bin directory --- etc/scripts/README.md | 8 +++- etc/scripts/release.hs | 96 +++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 54 deletions(-) mode change 100755 => 100644 etc/scripts/release.hs diff --git a/etc/scripts/README.md b/etc/scripts/README.md index 95769e9195..6bd5500a16 100644 --- a/etc/scripts/README.md +++ b/etc/scripts/README.md @@ -16,7 +16,6 @@ These must be installed in the PATH to use the release tool: - stack - git (for Windows, [msysgit](https://msysgit.github.io) is recommended). -- cabal (cabal-install) To create a signed binary package, you need: @@ -58,10 +57,15 @@ To create and upload Arch packages, you need: - [AWS CLI installed](http://docs.aws.amazon.com/cli/latest/userguide/installing.html). +Building +-------- + + (cd etc/scripts && stack build) + Invocation ---------- -Usage: `etc/scripts/release.hs [OPTIONS] TARGET` +Usage: `$(cd etc/scripts && stack exec which stack-release-script) [OPTIONS] TARGET` The tool must be run in the root of the working tree. diff --git a/etc/scripts/release.hs b/etc/scripts/release.hs old mode 100755 new mode 100644 index 9f99df4a0b..3362c2feca --- a/etc/scripts/release.hs +++ b/etc/scripts/release.hs @@ -1,6 +1,3 @@ -#!/usr/bin/env stack --- stack --install-ghc runghc --package=shake --package=extra --package=zip-archive --package=mime-types --package=http-types --package=http-conduit --package=text --package=conduit-combinators --package=conduit --package=case-insensitive --package=aeson --package=zlib --package tar -{-# OPTIONS_GHC -Wall -Werror #-} {-# LANGUAGE RecordWildCards #-} import Control.Applicative @@ -22,6 +19,7 @@ import System.Environment import System.Directory import System.IO.Error import System.Process +import System.Exit import qualified Codec.Archive.Tar as Tar import qualified Codec.Archive.Zip as Zip @@ -61,15 +59,13 @@ main = gArch = arch gBinarySuffix = "" gUploadLabel = Nothing - gLocalInstallRoot = "" -- Set to real value below. gProjectRoot = "" -- Set to real value velow. global0 = foldl (flip id) Global{..} flags -- Need to get paths after options since the '--arch' argument can effect them. localInstallRoot' <- getStackPath global0 "local-install-root" projectRoot' <- getStackPath global0 "project-root" let global = global0 - { gLocalInstallRoot = localInstallRoot' - , gProjectRoot = projectRoot' } + { gProjectRoot = projectRoot' } return $ Just $ rules global args where getStackPath global path = do @@ -146,24 +142,22 @@ rules global@Global{..} args = do copyFileChanged srcFile out releaseCheckDir binaryExeFileName %> \out -> do - need [installBinDir stackExeFileName] + need [releaseBinDir binaryName stackExeFileName] Stdout dirty <- cmd "git status --porcelain" when (not gAllowDirty && not (null (trim dirty))) $ error ("Working tree is dirty. Use --" ++ allowDirtyOptName ++ " option to continue anyway.") - let instExeFile = installBinDir stackExeFileName - tmpExeFile = installBinDir stackExeFileName <.> "tmp" - --EKB FIXME: once 'stack install --path' implemented, use it instead of this temp file. - liftIO $ renameFile instExeFile tmpExeFile - actionFinally - (do opt <- addPath [installBinDir] [] - -- () <- cmd opt stackProgName (stackArgs global) "build --pedantic --haddock --no-haddock-deps" - () <- cmd opt stackProgName (stackArgs global) "build --pedantic" - () <- cmd opt stackProgName (stackArgs global) "clean" - () <- cmd opt stackProgName (stackArgs global) "build --pedantic" - () <- cmd opt stackProgName (stackArgs global) "test --pedantic --flag stack:integration-tests" - return ()) - (renameFile tmpExeFile instExeFile) - copyFileChanged (installBinDir stackExeFileName) out + withTempDir $ \tmpDir -> do + let cmd0 = cmd (releaseBinDir binaryName stackExeFileName) + (stackArgs global) + ["--local-bin-path=" ++ tmpDir] + () <- cmd0 "install --pedantic --haddock --no-haddock-deps" + () <- cmd0 "install cabal-install" + let cmd' = cmd (AddPath [tmpDir] []) stackProgName (stackArgs global) + () <- cmd' "clean" + () <- cmd' "build --pedantic" + () <- cmd' "test --pedantic --flag stack:integration-tests" + return () + copyFileChanged (releaseBinDir binaryName stackExeFileName) out releaseDir binaryPkgZipFileName %> \out -> do stageFiles <- getBinaryPkgStageFiles @@ -172,7 +166,7 @@ rules global@Global{..} args = do entries <- forM stageFiles $ \stageFile -> do Zip.readEntry [Zip.OptLocation - (dropDirectoryPrefix (releaseStageDir binaryPkgStageDirName) stageFile) + (dropDirectoryPrefix (releaseStageDir binaryName) stageFile) False] stageFile let archive = foldr Zip.addEntryToArchive Zip.emptyArchive entries @@ -182,21 +176,21 @@ rules global@Global{..} args = do stageFiles <- getBinaryPkgStageFiles writeTarGz out releaseStageDir stageFiles - releaseStageDir binaryPkgStageDirName stackExeFileName %> \out -> do + releaseStageDir binaryName stackExeFileName %> \out -> do copyFileChanged (releaseDir binaryExeFileName) out - releaseStageDir (binaryPkgStageDirName ++ "//*") %> \out -> do + releaseStageDir (binaryName ++ "//*") %> \out -> do copyFileChanged - (dropDirectoryPrefix (releaseStageDir binaryPkgStageDirName) out) + (dropDirectoryPrefix (releaseStageDir binaryName) out) out releaseDir binaryExeFileName %> \out -> do - need [installBinDir stackExeFileName] + need [releaseBinDir binaryName stackExeFileName] case platformOS of Windows -> do -- Windows doesn't have or need a 'strip' command, so skip it. -- Instead, we sign the executable - liftIO $ copyFile (installBinDir stackExeFileName) out + liftIO $ copyFile (releaseBinDir binaryName stackExeFileName) out actionOnException (command_ [] "c:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Bin\\signtool.exe" ["sign" @@ -209,10 +203,10 @@ rules global@Global{..} args = do (removeFile out) Linux -> cmd "strip -p --strip-unneeded --remove-section=.comment -o" - [out, installBinDir stackExeFileName] + [out, releaseBinDir binaryName stackExeFileName] _ -> cmd "strip -o" - [out, installBinDir stackExeFileName] + [out, releaseBinDir binaryName stackExeFileName] releaseDir binaryPkgSignatureFileName %> \out -> do need [out -<.> ""] @@ -221,10 +215,13 @@ rules global@Global{..} args = do [ "-u", gGpgKey , dropExtension out ] - installBinDir stackExeFileName %> \out -> do + releaseBinDir binaryName stackExeFileName %> \out -> do alwaysRerun actionOnException - (cmd stackProgName (stackArgs global) "--install-ghc build --pedantic") + (cmd stackProgName + (stackArgs global) + ["--local-bin-path=" ++ takeDirectory out] + "--install-ghc install --pedantic") (removeFile out) debDistroRules ubuntuDistro ubuntuVersions @@ -357,8 +354,8 @@ rules global@Global{..} args = do getBinaryPkgStageFiles = do docFiles <- getDocFiles let stageFiles = concat - [[releaseStageDir binaryPkgStageDirName stackExeFileName] - ,map ((releaseStageDir binaryPkgStageDirName) ) docFiles] + [[releaseStageDir binaryName stackExeFileName] + ,map ((releaseStageDir binaryName) ) docFiles] need stageFiles return stageFiles @@ -392,7 +389,7 @@ rules global@Global{..} args = do releaseCheckDir = releaseDir "check" releaseStageDir = releaseDir "stage" - installBinDir = gLocalInstallRoot "bin" + releaseBinDir = releaseDir "bin" distroVersionDir DistroVersion{..} = releaseDir dvDistro dvVersion binaryPkgFileNames = [binaryPkgFileName, binaryPkgSignatureFileName] @@ -401,10 +398,19 @@ rules global@Global{..} args = do case platformOS of Windows -> binaryPkgZipFileName _ -> binaryPkgTarGzFileName - binaryPkgZipFileName = binaryName global <.> zipExt - binaryPkgTarGzFileName = binaryName global <.> tarGzExt - binaryPkgStageDirName = binaryName global - binaryExeFileName = binaryName global <.> exe + binaryPkgZipFileName = binaryName <.> zipExt + binaryPkgTarGzFileName = binaryName <.> tarGzExt + binaryExeFileName = binaryName <.> exe + binaryName = + concat + [ stackProgName + , "-" + , stackVersionStr global + , "-" + , display platformOS + , "-" + , display gArch + , if null gBinarySuffix then "" else "-" ++ gBinarySuffix ] stackExeFileName = stackProgName <.> exe debStagedDocDir dv = debStagingDir dv "usr/share/doc" stackProgName @@ -549,19 +555,6 @@ dropDirectoryPrefix prefix path = Nothing -> error ("dropDirectoryPrefix: cannot drop " ++ show prefix ++ " from " ++ show path) Just stripped -> stripped --- | Name of the release binary (e.g. @stack-x.y.x-os-arch[-variant]@) -binaryName :: Global -> String -binaryName global@Global{..} = - concat - [ stackProgName - , "-" - , stackVersionStr global - , "-" - , display platformOS - , "-" - , display gArch - , if null gBinarySuffix then "" else "-" ++ gBinarySuffix ] - -- | String representation of stack package version. stackVersionStr :: Global -> String stackVersionStr = @@ -646,7 +639,6 @@ instance FromJSON GithubReleaseAsset where -- | Global values and options. data Global = Global { gStackPackageDescription :: !PackageDescription - , gLocalInstallRoot :: !FilePath , gGpgKey :: !String , gAllowDirty :: !Bool , gGithubAuthToken :: !(Maybe String) From e22271f5ce9afa2cb5be3bad9cafa392c623f85c Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Tue, 13 Oct 2015 13:32:03 -0700 Subject: [PATCH 016/106] Add missed files --- .gitignore | 2 ++ etc/scripts/LICENSE | 30 +++++++++++++++++++++++ etc/scripts/Setup.hs | 2 ++ etc/scripts/stack-scripts.cabal | 42 +++++++++++++++++++++++++++++++++ etc/scripts/stack.yaml | 5 ++++ 5 files changed, 81 insertions(+) create mode 100644 etc/scripts/LICENSE create mode 100644 etc/scripts/Setup.hs create mode 100644 etc/scripts/stack-scripts.cabal create mode 100644 etc/scripts/stack.yaml diff --git a/.gitignore b/.gitignore index d8de0c4215..e76b2e3cc7 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ tags *.imports /.idea/ /*.iml +/src/highlight.js +/src/style.css diff --git a/etc/scripts/LICENSE b/etc/scripts/LICENSE new file mode 100644 index 0000000000..7d47dc0c71 --- /dev/null +++ b/etc/scripts/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2015, Emanuel Borsboom + +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 Emanuel Borsboom 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/etc/scripts/Setup.hs b/etc/scripts/Setup.hs new file mode 100644 index 0000000000..9a994af677 --- /dev/null +++ b/etc/scripts/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/etc/scripts/stack-scripts.cabal b/etc/scripts/stack-scripts.cabal new file mode 100644 index 0000000000..19bee40622 --- /dev/null +++ b/etc/scripts/stack-scripts.cabal @@ -0,0 +1,42 @@ +-- Initial scripts.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: stack-scripts +version: 0.0.0.0 +-- synopsis: +-- description: +license: BSD3 +license-file: LICENSE +author: Emanuel Borsboom +maintainer: manny@fpcomplete.com +-- copyright: +-- category: +build-type: Simple +extra-source-files: README.md +cabal-version: >=1.10 + +executable stack-release-script + main-is: release.hs + -- other-modules: + -- other-extensions: + build-depends: base >=4.8 && <5.0 + , Cabal + , aeson + , bytestring + , case-insensitive + , conduit + , conduit-combinators + , directory + , extra + , http-conduit + , http-types + , mime-types + , process + , resourcet + , shake + , tar + , text + , zip-archive + , zlib + -- hs-source-dirs: + default-language: Haskell2010 \ No newline at end of file diff --git a/etc/scripts/stack.yaml b/etc/scripts/stack.yaml new file mode 100644 index 0000000000..2dbed996fe --- /dev/null +++ b/etc/scripts/stack.yaml @@ -0,0 +1,5 @@ +resolver: lts-3.7 +packages: +- '.' +extra-deps: [] +flags: {} From f359cbea3551329f4d8fb28e725b4776a02ddbc6 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Wed, 14 Oct 2015 16:23:11 +0000 Subject: [PATCH 017/106] Add allow-newer config option (closes #922) --- ChangeLog.md | 7 +++++ doc/yaml_configuration.md | 13 +++++++++ src/Stack/Build/ConstructPlan.hs | 48 ++++++++++++++++++++++++-------- src/Stack/Config.hs | 1 + src/Stack/Types/Config.hs | 9 ++++++ 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0772ceb89b..dadfbee089 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,12 @@ ## Unreleased changes +Major changes: + +Other enhancements: + +* Added an `allow-newer` config option [#922](https://github.com/commercialhaskell/stack/issues/922) [#770](https://github.com/commercialhaskell/stack/issues/770) + +Bug fixes: ## v0.1.6.0 diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md index 25229fb7c0..dffa8bbe9b 100644 --- a/doc/yaml_configuration.md +++ b/doc/yaml_configuration.md @@ -346,3 +346,16 @@ apply-ghc-options: locals # all local packages, the default ``` Note that `everything` is a slightly dangerous value, as it can break invariants about your snapshot database. + +### allow-newer + +(Since 0.1.7) + +Ignore version bounds in .cabal files. Default is false. + +```yaml +allow-newer: true +``` + +Note that this also ignores lower bounds. The name "allow-newer" is chosen to +match the commonly used cabal option. diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 4da8ada03d..5fac9c63ce 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -3,6 +3,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} -- | Construct a @Plan@ for how to build module Stack.Build.ConstructPlan @@ -13,7 +14,7 @@ import Control.Exception.Lifted import Control.Monad import Control.Monad.Catch (MonadCatch) import Control.Monad.IO.Class -import Control.Monad.Logger (MonadLogger) +import Control.Monad.Logger (MonadLogger, logWarn) import Control.Monad.RWS.Strict import Control.Monad.Trans.Resource import qualified Data.ByteString.Char8 as S8 @@ -82,10 +83,12 @@ data W = W -- ^ why a local package is considered dirty , wDeps :: !(Set PackageName) -- ^ Packages which count as dependencies + , wWarnings :: !([Text] -> [Text]) + -- ^ Warnings } instance Monoid W where - mempty = W mempty mempty mempty mempty - mappend (W a b c d) (W w x y z) = W (mappend a w) (mappend b x) (mappend c y) (mappend d z) + mempty = W mempty mempty mempty mempty mempty + mappend (W a b c d e) (W w x y z z') = W (mappend a w) (mappend b x) (mappend c y) (mappend d z) (mappend e z') type M = RWST Ctx @@ -143,7 +146,9 @@ constructPlan mbp0 baseConfigOpts0 locals extraToBuild0 locallyRegistered loadPa let inner = do mapM_ onWanted $ filter lpWanted locals mapM_ (addDep False) $ Set.toList extraToBuild0 - ((), m, W efinals installExes dirtyReason deps) <- liftIO $ runRWST inner (ctx econfig latest) M.empty + ((), m, W efinals installExes dirtyReason deps warnings) <- + liftIO $ runRWST inner (ctx econfig latest) M.empty + mapM_ $logWarn (warnings []) let toEither (_, Left e) = Left e toEither (k, Right v) = Right (k, v) (errlibs, adrs) = partitionEithers $ map toEither $ M.toList m @@ -398,14 +403,33 @@ addPackageDeps treatAsDep package = do UnknownPackage name -> assert (name == depname) NotInBuildPlan _ -> Couldn'tResolveItsDependencies in return $ Left (depname, (range, mlatest, bd)) - Right adr | not $ adrVersion adr `withinRange` range -> - return $ Left (depname, (range, mlatest, DependencyMismatch $ adrVersion adr)) - Right (ADRToInstall task) -> return $ Right - (Set.singleton $ taskProvides task, Map.empty, taskLocation task) - Right (ADRFound loc _ (Executable _)) -> return $ Right - (Set.empty, Map.empty, loc) - Right (ADRFound loc _ (Library ident gid)) -> return $ Right - (Set.empty, Map.singleton ident gid, loc) + Right adr -> do + inRange <- if adrVersion adr `withinRange` range + then return True + else do + allowNewer <- asks $ configAllowNewer . getConfig + if allowNewer + then do + let msg = T.concat + [ "WARNING: Ignoring out of range dependency: " + , T.pack $ packageIdentifierString $ PackageIdentifier depname (adrVersion adr) + , ". " + , T.pack $ packageNameString $ packageName package + , " requires: " + , versionRangeText range + ] + tell mempty { wWarnings = (msg:) } + return True + else return False + if inRange + then case adr of + ADRToInstall task -> return $ Right + (Set.singleton $ taskProvides task, Map.empty, taskLocation task) + ADRFound loc _ (Executable _) -> return $ Right + (Set.empty, Map.empty, loc) + ADRFound loc _ (Library ident gid) -> return $ Right + (Set.empty, Map.singleton ident gid, loc) + else return $ Left (depname, (range, mlatest, DependencyMismatch $ adrVersion adr)) case partitionEithers deps of ([], pairs) -> return $ Right $ mconcat pairs (errs, _) -> return $ Left $ DependencyPlanFailures diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs index 0ddd3e45ab..f646efd5bf 100644 --- a/src/Stack/Config.hs +++ b/src/Stack/Config.hs @@ -191,6 +191,7 @@ configFromConfigMonoid configStackRoot configUserConfigPath mproject configMonoi configExplicitSetupDeps = configMonoidExplicitSetupDeps configRebuildGhcOptions = fromMaybe False configMonoidRebuildGhcOptions configApplyGhcOptions = fromMaybe AGOLocals configMonoidApplyGhcOptions + configAllowNewer = fromMaybe False configMonoidAllowNewer return Config {..} diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index f3e87a8a9b..c3d16814e1 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -151,6 +151,9 @@ data Config = -- ^ Rebuild on GHC options changes ,configApplyGhcOptions :: !ApplyGhcOptions -- ^ Which packages to ghc-options on the command line apply to? + ,configAllowNewer :: !Bool + -- ^ Ignore version ranges in .cabal files. Funny naming chosen to + -- match cabal. } -- | Which packages to ghc-options on the command line apply to? @@ -605,6 +608,9 @@ data ConfigMonoid = ,configMonoidRebuildGhcOptions :: !(Maybe Bool) -- ^ See 'configMonoidRebuildGhcOptions' ,configMonoidApplyGhcOptions :: !(Maybe ApplyGhcOptions) + -- ^ See 'configApplyGhcOptions' + ,configMonoidAllowNewer :: !(Maybe Bool) + -- ^ See 'configMonoidAllowNewer' } deriving Show @@ -640,6 +646,7 @@ instance Monoid ConfigMonoid where , configMonoidExplicitSetupDeps = mempty , configMonoidRebuildGhcOptions = Nothing , configMonoidApplyGhcOptions = Nothing + , configMonoidAllowNewer = Nothing } mappend l r = ConfigMonoid { configMonoidDockerOpts = configMonoidDockerOpts l <> configMonoidDockerOpts r @@ -673,6 +680,7 @@ instance Monoid ConfigMonoid where , configMonoidExplicitSetupDeps = configMonoidExplicitSetupDeps l <> configMonoidExplicitSetupDeps r , configMonoidRebuildGhcOptions = configMonoidRebuildGhcOptions l <|> configMonoidRebuildGhcOptions r , configMonoidApplyGhcOptions = configMonoidApplyGhcOptions l <|> configMonoidApplyGhcOptions r + , configMonoidAllowNewer = configMonoidAllowNewer l <|> configMonoidAllowNewer r } instance FromJSON (ConfigMonoid, [JSONWarning]) where @@ -734,6 +742,7 @@ parseConfigMonoidJSON obj = do >>= fmap Map.fromList . mapM handleExplicitSetupDep . Map.toList configMonoidRebuildGhcOptions <- obj ..:? "rebuild-ghc-options" configMonoidApplyGhcOptions <- obj ..:? "apply-ghc-options" + configMonoidAllowNewer <- obj ..:? "allow-newer" return ConfigMonoid {..} where From 956489f71f0b27714ccfd1431415d4bc9a13a6a4 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Wed, 14 Oct 2015 16:23:20 +0000 Subject: [PATCH 018/106] Minor typo correction --- src/Stack/Package.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index 2b467a4c94..a3a82155ee 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -983,7 +983,7 @@ warnMultiple name candidate rest = $logWarn ("There were multiple candidates for the Cabal entry \"" <> showName name <> - "(" <> + "\" (" <> T.intercalate "," (map (T.pack . toFilePath) rest) <> "), picking " <> T.pack (toFilePath candidate)) From e26dc62fb569d25a9ef9cf14c610d06735bdbd67 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Wed, 14 Oct 2015 19:39:24 -0700 Subject: [PATCH 019/106] Parse package key out of package.conf.inplace #785 --- src/Stack/Build/Coverage.hs | 17 +++++++++++++---- src/Stack/Build/Execute.hs | 8 +------- src/Stack/GhcPkg.hs | 13 ------------- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index d108d83700..9bf61dce37 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -20,7 +20,7 @@ import Control.Monad.Logger import Control.Monad.Reader (MonadReader, asks) import Control.Monad.Trans.Resource import qualified Data.ByteString.Char8 as S8 -import Data.Foldable (forM_) +import Data.Foldable (forM_, asum) import Data.Function import Data.List import qualified Data.Map.Strict as Map @@ -69,8 +69,8 @@ tixFilePath pkgId tixName = do -- | Generates the HTML coverage report and shows a textual coverage -- summary for a package. generateHpcReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => Package -> [Text] -> (PackageName -> m (Maybe Text)) -> m () -generateHpcReport package tests getGhcPkgKey = do + => Path Abs Dir -> Package -> [Text] -> m () +generateHpcReport pkgDir package tests = do -- If we're using > GHC 7.10, the hpc 'include' parameter must specify a -- ghc package key. See -- https://github.com/commercialhaskell/stack/issues/785 @@ -81,7 +81,7 @@ generateHpcReport package tests getGhcPkgKey = do if getGhcVersion compilerVersion < $(mkVersion "7.10") then return pkgId else do - mghcPkgKey <- getGhcPkgKey (packageName package) + mghcPkgKey <- findPackageKeyForBuiltPackage pkgDir (packageIdentifier package) case mghcPkgKey of Nothing -> fail $ "Before computing test coverage report, failed to find GHC package key for " ++ T.unpack pkgName Just ghcPkgKey -> return $ T.unpack ghcPkgKey @@ -257,3 +257,12 @@ generateHpcMarkupIndex = do pathToHtml :: Path b t -> Text pathToHtml = T.dropWhileEnd (=='/') . LT.toStrict . htmlEscape . LT.pack . toFilePath + +findPackageKeyForBuiltPackage :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env) + => Path Abs Dir -> PackageIdentifier -> m (Maybe Text) +findPackageKeyForBuiltPackage pkgDir pkgId = do + distDir <- distDirFromDir pkgDir + path <- liftM (distDir ) $ + parseRelFile ("package.conf.inplace/" ++ packageIdentifierString pkgId ++ "-inplace.conf") + contents <- liftIO $ T.readFile (toFilePath path) + return $ asum (map (T.stripPrefix "key: ") (T.lines contents)) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 4ae6844c44..3f9aa11b26 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1192,13 +1192,7 @@ singleTest runInBase topts lptb ac ee task installedMap = do ] return $ Map.singleton testName Nothing - when needHpc $ do - wc <- getWhichCompiler - let pkgDbs = - [ bcoSnapDB (eeBaseConfigOpts ee) - , bcoLocalDB (eeBaseConfigOpts ee) - ] - generateHpcReport package testsToRun (findGhcPkgKey (eeEnvOverride ee) wc pkgDbs) + when needHpc $ generateHpcReport pkgDir package testsToRun bs <- liftIO $ case mlogFile of diff --git a/src/Stack/GhcPkg.hs b/src/Stack/GhcPkg.hs index 5aabce49d6..8f8b2c9147 100644 --- a/src/Stack/GhcPkg.hs +++ b/src/Stack/GhcPkg.hs @@ -11,7 +11,6 @@ module Stack.GhcPkg (findGhcPkgId - ,findGhcPkgKey ,getGlobalDB ,EnvOverride ,envHelper @@ -147,18 +146,6 @@ findGhcPkgId menv wc pkgDbs name = do Just !pid -> return (parseGhcPkgId (T.encodeUtf8 pid)) _ -> return Nothing --- | Get the package key e.g. @foo_9bTCpMF7G4UFWJJvtDrIdB@. --- --- NOTE: GHC > 7.10 only! Will always yield 'Nothing' otherwise. -findGhcPkgKey :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride - -> WhichCompiler - -> [Path Abs Dir] -- ^ package databases - -> PackageName - -> m (Maybe Text) -findGhcPkgKey menv wc pkgDbs name = - findGhcPkgField menv wc pkgDbs (packageNameString name) "key" - -- | Get the version of the package findGhcPkgVersion :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) => EnvOverride From a4504128714539d1951e8798bd759cebb0723818 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Wed, 14 Oct 2015 19:43:16 -0700 Subject: [PATCH 020/106] doc: fix travis stack download command --- doc/GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/GUIDE.md b/doc/GUIDE.md index 1b22b3de86..1bdbd114fd 100644 --- a/doc/GUIDE.md +++ b/doc/GUIDE.md @@ -1603,7 +1603,7 @@ before_install: # Download and unpack the stack executable - mkdir -p ~/.local/bin - export PATH=$HOME/.local/bin:$PATH -- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.6.0/stack-0.1.6.0-linux-x86_64.tar.gz | tar xz --strip-components=1 -C ~/.local/bin '*/stack' +- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.6.0/stack-0.1.6.0-linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' # This line does all of the work: installs GHC if necessary, build the library, # executables, and test suites, and runs the test suites. --no-terminal works From d5ef6f5bd0c768c071182d753f05e5f54833215b Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Wed, 14 Oct 2015 19:47:56 -0700 Subject: [PATCH 021/106] README links point to release docs on Github (fixes #1157) --- README.md | 50 +++++++++++++++++++------------------- doc/install_and_upgrade.md | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 076dc9cc44..cbf259ef60 100644 --- a/README.md +++ b/README.md @@ -21,17 +21,17 @@ It features: Downloads are available by operating system: -* [Windows](doc/install_and_upgrade.md#windows) -* [OS X](doc/install_and_upgrade.md#os-x) -* [Ubuntu](doc/install_and_upgrade.md#ubuntu) -* [Debian](doc/install_and_upgrade.md#debian) -* [CentOS / Red Hat / Amazon Linux](doc/install_and_upgrade.md#centos--red-hat--amazon-linux) -* [Fedora](doc/install_and_upgrade.md#fedora) -* [Arch Linux](doc/install_and_upgrade.md#arch-linux) -* [NixOS](doc/install_and_upgrade.md#nixos) -* [Linux (general)](doc/install_and_upgrade.md#linux) - -[Upgrade instructions](doc/install_and_upgrade.md#upgrade) +* [Windows](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#windows) +* [OS X](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#os-x) +* [Ubuntu](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#ubuntu) +* [Debian](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#debian) +* [CentOS / Red Hat / Amazon Linux](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#centos--red-hat--amazon-linux) +* [Fedora](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#fedora) +* [Arch Linux](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#arch-linux) +* [NixOS](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#nixos) +* [Linux (general)](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#linux) + +[Upgrade instructions](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#upgrade) Note: if you are using cabal-install to install stack, you may need to pass a constraint to work around a @@ -138,13 +138,13 @@ stack build #### Complete guide to stack This repository also contains a complete [user guide to using stack -](doc/GUIDE.md), covering all of the most common use cases. +](https://github.com/commercialhaskell/stack/blob/release/doc/GUIDE.md), covering all of the most common use cases. #### Questions, Feedback, Discussion * For frequently asked questions about detailed or specific use-cases, please - see [the FAQ](doc/faq.md). + see [the FAQ](https://github.com/commercialhaskell/stack/blob/release/doc/faq.md). * For general questions, comments, feedback and support please write to [the stack mailing list](https://groups.google.com/d/forum/haskell-stack). * For bugs, issues, or requests please @@ -178,27 +178,27 @@ can address these concerns. ## Documentation Table Of Contents * Project Documentation - * [Maintainer Guide](doc/MAINTAINER_GUIDE.md): includes releasing information - * [Signing Key](doc/SIGNING_KEY.md): downloadable stack binaries are signed + * [Maintainer Guide](https://github.com/commercialhaskell/stack/blob/release/doc/MAINTAINER_GUIDE.md): includes releasing information + * [Signing Key](https://github.com/commercialhaskell/stack/blob/release/doc/SIGNING_KEY.md): downloadable stack binaries are signed with this key * Tool Documentation - * [Build Command](doc/build_command.md): reference for the syntax of the + * [Build Command](https://github.com/commercialhaskell/stack/blob/release/doc/build_command.md): reference for the syntax of the build command and the command line targets - * [Dependency Visualization](doc/dependency_visualization.md): uses Graphviz - * [Docker Integration](doc/docker_integration.md) - * [FAQ](doc/faq.md): frequently asked questions about detailed or specific + * [Dependency Visualization](https://github.com/commercialhaskell/stack/blob/release/doc/dependency_visualization.md): uses Graphviz + * [Docker Integration](https://github.com/commercialhaskell/stack/blob/release/doc/docker_integration.md) + * [FAQ](https://github.com/commercialhaskell/stack/blob/release/doc/faq.md): frequently asked questions about detailed or specific use-cases - * [Install/Upgrade](doc/install_and_upgrade.md): a list of downloads + * [Install/Upgrade](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md): a list of downloads available by operating system, installation instructions, and upgrade instructions - * [Nonstandard Project Initialization](doc/nonstandard_project_init.md) - * [Shell Autocompletion](doc/shell_autocompletion.md) - * [User Guide](doc/GUIDE.md): in-depth tutorial covering the most common use + * [Nonstandard Project Initialization](https://github.com/commercialhaskell/stack/blob/release/doc/nonstandard_project_init.md) + * [Shell Autocompletion](https://github.com/commercialhaskell/stack/blob/release/doc/shell_autocompletion.md) + * [User Guide](https://github.com/commercialhaskell/stack/blob/release/doc/GUIDE.md): in-depth tutorial covering the most common use cases and all major stack features (requires no prior Haskell tooling experience) - * [YAML Configuration](doc/yaml_configuration.md): reference for writing + * [YAML Configuration](https://github.com/commercialhaskell/stack/blob/release/doc/yaml_configuration.md): reference for writing `stack.yaml` files * Advanced Documentation - * [Architecture](doc/architecture.md): reference for people curious about + * [Architecture](https://github.com/commercialhaskell/stack/blob/release/doc/architecture.md): reference for people curious about stack internals, wanting to get involved deeply in the codebase, or wanting to use stack in unusual ways diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index fd9e7155a9..7d4818bc64 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -32,7 +32,7 @@ We generally test on the current version of OS X, but stack is known to work on * Ubuntu 15.10 (amd64): - echo 'deb http://download.fpcomplete.com/ubuntu/wily stable main'|sudo tee /etc/apt/sources.list.d/fpco.list + echo 'deb http://download.fpcomplete.com/ubuntu/wily stable main'|sudo tee /etc/apt/sources.list.d/fpco.list * Ubuntu 15.04 (amd64): From df543398f231b6cff5918d7b964835ef44dac5f8 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Thu, 15 Oct 2015 04:44:02 +0000 Subject: [PATCH 022/106] When a Hackage revision invalidates a build plan in a snapshot, trust the snapshot #770 --- ChangeLog.md | 1 + src/Stack/Build/ConstructPlan.hs | 40 ++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index dadfbee089..9643c45552 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,7 @@ Major changes: Other enhancements: * Added an `allow-newer` config option [#922](https://github.com/commercialhaskell/stack/issues/922) [#770](https://github.com/commercialhaskell/stack/issues/770) +* When a Hackage revision invalidates a build plan in a snapshot, trust the snapshot [#770](https://github.com/commercialhaskell/stack/issues/770) Bug fixes: diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 5fac9c63ce..303a2db817 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -407,20 +407,32 @@ addPackageDeps treatAsDep package = do inRange <- if adrVersion adr `withinRange` range then return True else do + let warn reason = do + tell mempty { wWarnings = (msg:) } + where + msg = T.concat + [ "WARNING: Ignoring out of range dependency" + , reason + , ": " + , T.pack $ packageIdentifierString $ PackageIdentifier depname (adrVersion adr) + , ". " + , T.pack $ packageNameString $ packageName package + , " requires: " + , versionRangeText range + ] allowNewer <- asks $ configAllowNewer . getConfig if allowNewer then do - let msg = T.concat - [ "WARNING: Ignoring out of range dependency: " - , T.pack $ packageIdentifierString $ PackageIdentifier depname (adrVersion adr) - , ". " - , T.pack $ packageNameString $ packageName package - , " requires: " - , versionRangeText range - ] - tell mempty { wWarnings = (msg:) } + warn " (allow-newer enabled)" return True - else return False + else do + x <- inSnapshot (packageName package) (packageVersion package) + y <- inSnapshot depname (adrVersion adr) + if x && y + then do + warn " (trusting snapshot over Hackage revisions)" + return True + else return False if inRange then case adr of ADRToInstall task -> return $ Right @@ -601,3 +613,11 @@ stripNonDeps deps plan = plan markAsDep :: PackageName -> M () markAsDep name = tell mempty { wDeps = Set.singleton name } + +-- | Is the given package/version combo defined in the snapshot? +inSnapshot :: PackageName -> Version -> M Bool +inSnapshot name version = do + p <- asks mbp + return $ fromMaybe False $ do + mpi <- Map.lookup name (mbpPackages p) + return $ mpiVersion mpi == version From ddc45880bbf2688c7d3ece8c2ec0f432b35fe3b9 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Thu, 15 Oct 2015 05:04:50 +0000 Subject: [PATCH 023/106] Don't trust local packages for revision ignoring (thanks @mgsloan) --- src/Stack/Build/ConstructPlan.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 303a2db817..86f112b357 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -107,6 +107,7 @@ data Ctx = Ctx , extraToBuild :: !(Set PackageName) , latestVersions :: !(Map PackageName Version) , wanted :: !(Set PackageName) + , localNames :: !(Set PackageName) } instance HasStackRoot Ctx @@ -188,6 +189,7 @@ constructPlan mbp0 baseConfigOpts0 locals extraToBuild0 locallyRegistered loadPa , extraToBuild = extraToBuild0 , latestVersions = latest , wanted = wantedLocalPackages locals + , localNames = Set.fromList $ map (packageName . lpPackage) locals } -- TODO Currently, this will only consider and install tools from the -- snapshot. It will not automatically install build tools from extra-deps @@ -618,6 +620,8 @@ markAsDep name = tell mempty { wDeps = Set.singleton name } inSnapshot :: PackageName -> Version -> M Bool inSnapshot name version = do p <- asks mbp + ls <- asks localNames return $ fromMaybe False $ do + guard $ not $ name `Set.member` ls mpi <- Map.lookup name (mbpPackages p) return $ mpiVersion mpi == version From b188f022ed51e36190c8048e2a2667cfd41ae766 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Wed, 14 Oct 2015 22:45:17 -0700 Subject: [PATCH 024/106] Revert "Parse package key out of package.conf.inplace #785" This reverts commit e26dc62fb569d25a9ef9cf14c610d06735bdbd67. --- src/Stack/Build/Coverage.hs | 17 ++++------------- src/Stack/Build/Execute.hs | 8 +++++++- src/Stack/GhcPkg.hs | 13 +++++++++++++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index 9bf61dce37..d108d83700 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -20,7 +20,7 @@ import Control.Monad.Logger import Control.Monad.Reader (MonadReader, asks) import Control.Monad.Trans.Resource import qualified Data.ByteString.Char8 as S8 -import Data.Foldable (forM_, asum) +import Data.Foldable (forM_) import Data.Function import Data.List import qualified Data.Map.Strict as Map @@ -69,8 +69,8 @@ tixFilePath pkgId tixName = do -- | Generates the HTML coverage report and shows a textual coverage -- summary for a package. generateHpcReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => Path Abs Dir -> Package -> [Text] -> m () -generateHpcReport pkgDir package tests = do + => Package -> [Text] -> (PackageName -> m (Maybe Text)) -> m () +generateHpcReport package tests getGhcPkgKey = do -- If we're using > GHC 7.10, the hpc 'include' parameter must specify a -- ghc package key. See -- https://github.com/commercialhaskell/stack/issues/785 @@ -81,7 +81,7 @@ generateHpcReport pkgDir package tests = do if getGhcVersion compilerVersion < $(mkVersion "7.10") then return pkgId else do - mghcPkgKey <- findPackageKeyForBuiltPackage pkgDir (packageIdentifier package) + mghcPkgKey <- getGhcPkgKey (packageName package) case mghcPkgKey of Nothing -> fail $ "Before computing test coverage report, failed to find GHC package key for " ++ T.unpack pkgName Just ghcPkgKey -> return $ T.unpack ghcPkgKey @@ -257,12 +257,3 @@ generateHpcMarkupIndex = do pathToHtml :: Path b t -> Text pathToHtml = T.dropWhileEnd (=='/') . LT.toStrict . htmlEscape . LT.pack . toFilePath - -findPackageKeyForBuiltPackage :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env) - => Path Abs Dir -> PackageIdentifier -> m (Maybe Text) -findPackageKeyForBuiltPackage pkgDir pkgId = do - distDir <- distDirFromDir pkgDir - path <- liftM (distDir ) $ - parseRelFile ("package.conf.inplace/" ++ packageIdentifierString pkgId ++ "-inplace.conf") - contents <- liftIO $ T.readFile (toFilePath path) - return $ asum (map (T.stripPrefix "key: ") (T.lines contents)) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 3f9aa11b26..4ae6844c44 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1192,7 +1192,13 @@ singleTest runInBase topts lptb ac ee task installedMap = do ] return $ Map.singleton testName Nothing - when needHpc $ generateHpcReport pkgDir package testsToRun + when needHpc $ do + wc <- getWhichCompiler + let pkgDbs = + [ bcoSnapDB (eeBaseConfigOpts ee) + , bcoLocalDB (eeBaseConfigOpts ee) + ] + generateHpcReport package testsToRun (findGhcPkgKey (eeEnvOverride ee) wc pkgDbs) bs <- liftIO $ case mlogFile of diff --git a/src/Stack/GhcPkg.hs b/src/Stack/GhcPkg.hs index 8f8b2c9147..5aabce49d6 100644 --- a/src/Stack/GhcPkg.hs +++ b/src/Stack/GhcPkg.hs @@ -11,6 +11,7 @@ module Stack.GhcPkg (findGhcPkgId + ,findGhcPkgKey ,getGlobalDB ,EnvOverride ,envHelper @@ -146,6 +147,18 @@ findGhcPkgId menv wc pkgDbs name = do Just !pid -> return (parseGhcPkgId (T.encodeUtf8 pid)) _ -> return Nothing +-- | Get the package key e.g. @foo_9bTCpMF7G4UFWJJvtDrIdB@. +-- +-- NOTE: GHC > 7.10 only! Will always yield 'Nothing' otherwise. +findGhcPkgKey :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) + => EnvOverride + -> WhichCompiler + -> [Path Abs Dir] -- ^ package databases + -> PackageName + -> m (Maybe Text) +findGhcPkgKey menv wc pkgDbs name = + findGhcPkgField menv wc pkgDbs (packageNameString name) "key" + -- | Get the version of the package findGhcPkgVersion :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) => EnvOverride From c0a1120faacd51cdb506094238f735b46210b20b Mon Sep 17 00:00:00 2001 From: Luke Iannini Date: Sat, 3 Oct 2015 02:53:39 -0700 Subject: [PATCH 025/106] Use platform-specific search path separators --- src/Stack/Ide.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Stack/Ide.hs b/src/Stack/Ide.hs index 715ef70f4b..c85360fc76 100644 --- a/src/Stack/Ide.hs +++ b/src/Stack/Ide.hs @@ -33,7 +33,7 @@ import Stack.Types import Stack.Types.Internal import System.Environment (lookupEnv) import System.Process.Run - +import System.FilePath (searchPathSeparator) -- | Launch a GHCi IDE for the given local project targets with the -- given options and configure it with the load paths and extensions -- of those targets. @@ -52,11 +52,11 @@ ide targets useropts = do mpath <- liftIO $ lookupEnv "PATH" bindirs <- extraBinDirs `ap` return True {- include local bin -} let pkgdbs = - ["--package-db=" <> toFilePath depsdb <> ":" <> toFilePath localdb] + ["--package-db=" <> toFilePath depsdb <> [searchPathSeparator] <> toFilePath localdb] paths = [ "--ide-backend-tools-path=" <> - intercalate ":" (map toFilePath bindirs) <> - (maybe "" (':' :) mpath)] + intercalate [searchPathSeparator] (map toFilePath bindirs) <> + (maybe "" (searchPathSeparator :) mpath)] args = ["--verbose"] <> ["--include=" <> includeDirs pkgopts] <> ["--local-work-dir=" ++ toFilePath pwd] <> @@ -74,7 +74,7 @@ ide targets useropts = do where includeDirs pkgopts = intercalate - ":" + [searchPathSeparator] (mapMaybe (stripPrefix "--ghc-option=-i") pkgopts) From 3b7e8afe3a6d7714b57d120755169474c455f6bf Mon Sep 17 00:00:00 2001 From: Denis Redozubov Date: Thu, 15 Oct 2015 20:01:21 +0300 Subject: [PATCH 026/106] fix wrong image command in docs --- doc/yaml_configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md index dffa8bbe9b..a4cd3c95d0 100644 --- a/doc/yaml_configuration.md +++ b/doc/yaml_configuration.md @@ -102,7 +102,7 @@ Flags will only affect packages in your `packages` and `extra-deps` settings. Packages that come from the snapshot global database or are not affected. ### image -The image settings are used for the creation of container images using `stack container image`, e.g. +The image settings are used for the creation of container images using `stack image container`, e.g. ```yaml image: container: From e6f23cf3250c1c93aceb87d5a99268f949996c47 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Thu, 15 Oct 2015 10:45:47 -0700 Subject: [PATCH 027/106] Release process documentation updates for v0.1.6.0 --- doc/MAINTAINER_GUIDE.md | 154 +++++++++++++++++++----- etc/scripts/README.md | 10 +- etc/scripts/osx-release.sh | 7 ++ etc/scripts/vagrant-distros.sh | 1 + etc/scripts/vagrant-releases.sh | 28 +++++ etc/scripts/windows-releases.bat | 16 +++ etc/vagrant/centos-6-i386/Vagrantfile | 17 ++- etc/vagrant/centos-6-x86_64/Vagrantfile | 9 +- etc/vagrant/centos-7-x86_64/Vagrantfile | 9 +- etc/vagrant/debian-7-amd64/Vagrantfile | 5 +- etc/vagrant/debian-7-i386/Vagrantfile | 32 +++-- 11 files changed, 222 insertions(+), 66 deletions(-) create mode 100755 etc/scripts/osx-release.sh create mode 120000 etc/scripts/vagrant-distros.sh create mode 100755 etc/scripts/vagrant-releases.sh create mode 100644 etc/scripts/windows-releases.bat diff --git a/doc/MAINTAINER_GUIDE.md b/doc/MAINTAINER_GUIDE.md index aab6924b5d..5f8861d639 100644 --- a/doc/MAINTAINER_GUIDE.md +++ b/doc/MAINTAINER_GUIDE.md @@ -1,38 +1,132 @@ +## Pre-release checks + The following should be tested minimally before a release is considered good -to go. This list will likely expand over time: - -* Run `etc/scripts/release.hs check` on Linux (32-bit and 64-bit), Windows (`--arch=i386` and `--arch=x86_64`), and OS X. See its - [README](../etc/scripts/README.md#release.hs) for build and invocation instructions. - This performs the following checks automatically: - * `stack install && stack clean && stack install --pedantic && stack test --flag stack:integration-tests` on Linux, Windows, and OS X, which covers: - * Self-hosting - * Unit tests - * Integration tests - * stack can install GHC - * Working tree is clean. -* Ensure that `stack --version` gives the correct version number and Git hash, and does not have a dirty tree +to go: + +* Integration tests pass on a representative sample of platforms: `stack test + --flag stack:integration-tests`. The actual release script will perform a more + thorough test for every platform/variant prior to uploading, so this is just a + pre-check * stack can build the wai repo * Running `stack build` a second time on either stack or wai is a no-op -* Build something that depends on `happy` (suggestion: `hlint`), since `happy` has special logic for moving around the `dist` directory -* Make sure to bump the version number in the .cabal file and the ChangeLog appropriately -* Review man page and other documentation for any changes that need to be made. +* Build something that depends on `happy` (suggestion: `hlint`), since `happy` + has special logic for moving around the `dist` directory +* Make sure to bump the version number in the .cabal file and the ChangeLog + appropriately (check for any entries that snuck into the previous version's + changes) +* In release candidate, remove the Changelog's "unreleased changes" section +* Review documentation for any changes that need to be made + * Search for old Stack version and replace with new version +* Ensure all `doc/*.md` files are listed in `stack.cabal`'s 'extra-source-files` +* Check that any new Linux distribution versions added to + `etc/scripts/release.hs` and `etc/scripts/vagrant-releases.sh` + +## Release process + +See +[stack-release-script's README](https://github.com/commercialhaskell/stack/blob/master/etc/scripts/README.md#prerequisites) +for requirements to perform the release, and more details about the tool. + +* Create a draft Github release with tag `vX.Y.Z` (where X.Y.Z is the stack + package's version) + +* On each machine you'll be releasing from, set environment variables: + `GITHUB_AUTHORIZATION_TOKEN`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` + +* On a machine with Vagrant installed: + * Run `etc/scripts/vagrant-releases.sh` + +* On Mac OS X: + * Run `etc/scripts/osx-release.sh` + +* On Windows: + * Ensure your working tree is in `C:\stack` (or a similarly short path) + * Run `etc\scripts\windows-releases.bat` + +* Push signed Git tag, matching Github release tag name, e.g.: `git tag -u + 9BEFB442 vX.Y.Z && git push origin vX.Y.Z` + +* Reset the `release` branch to the released commit, e.g.: `git merge --ff-only + vX.Y.Z && git push origin release` + +* Publish Github release + +* Edit + [stack-setup-2.yaml](https://github.com/fpco/stackage-content/blob/master/stack/stack-setup-2.yaml), + and add the new linux64 stack bindist + +* Upload package to Hackage: `stack upload . --pvp-bounds=both` + + Note: due to a + Cabal pretty-printer bug, this may fail with a syntax error. If so, use + `stack upload .`, then run `stack sdist --pvp-bounds=both`, and use + Hackage's + [edit package information](http://hackage.haskell.org/package/stack/maintain) + feature to paste the bounds in from the sdist's `stack.cabal`. + +* On a machine with Vagrant installed: + * Run `etc/scripts/vagrant-distros.sh` + +* Update in Arch Linux's + [haskell-stack.git](ssh+git://aur@aur.archlinux.org/haskell-stack.git): + `PKGBUILD` and `.SRCINFO` + * Be sure to reset `pkgrel` in both files, and update the SHA1 sum + +* Submit a PR for the + [haskell-stack Homebrew formula](https://github.com/Homebrew/homebrew/blob/master/Library/Formula/haskell-stack.rb). + The commit message should just be `haskell-stack `. + +* [Build new MinGHC distribution](#build_minghc) + +* [Upload haddocks to Hackage](#upload_haddocks), if hackage couldn't build on its own + +* Announce to haskell-cafe, commercialhaskell, and haskell-stack mailing lists + +# Extra steps + +## Upload haddocks to Hackage + +* Set `STACKVER` environment variable to the Stack version (e.g. `0.1.6.0`) +* Run: + +``` +STACKDOCDIR=stack-$STACKVER-docs +rm -rf _release/$STACKDOCDIR +mkdir -p _release +cp -r $(stack path --local-doc-root)/stack-$STACKVER _release/$STACKDOCDIR +sed -i '' 's/href="\.\.\/\([^/]*\)\//href="..\/..\/\1\/docs\//g' _release/$STACKDOCDIR/*.html +(cd _release && tar cvz --format=ustar -f $STACKDOCDIR.tar.gz $STACKDOCDIR) +curl -X PUT \ + -H 'Content-Type: application/x-tar' \ + -H 'Content-Encoding: gzip' \ + -u borsboom \ + --data-binary "@_release/$STACKDOCDIR.tar.gz" \ + "https://hackage.haskell.org/package/stack-$STACKVER/docs" +``` -Release checklist after testing: +## Build MinGHC -* Create a draft Github release with tag `vX.Y.Z` (where X.Y.Z is the stack package's version). -* Run `etc/scripts/release.hs release` on Linux (Debian 7 32-bit [Vagrantfile](https://github.com/commercialhaskell/stack/tree/master/etc/vagrant/debian-7-i386)/64-bit [Vagrantfile](https://github.com/commercialhaskell/stack/tree/master/etc/vagrant/debian-7-amd64)), Windows (`--arch=i386` and `--arch=x86_64`), and OS X. This performs the following tasks automatically: - * Binaries for Linux, Windows, and OS X uploaded to draft Github release. -* Run `etc/scripts/release.hs --binary-variant=gmp4 release` on CentOS 6 32-bit [Vagrantfile](https://github.com/commercialhaskell/stack/tree/master/etc/vagrant/centos-6-i386)/64-bit [Vagrantfile](centos-6-x86_64)). -* Run `etc/scripts/release.hs ubuntu-upload debian-upload` in Linux (Ubuntu or Debian - [Vagrantfile](https://github.com/commercialhaskell/stack/tree/master/etc/vagrant/debian-7-amd64)) -* Run `etc/scripts/release.hs centos-upload fedora-upload` on Linux (CentOS or Fedora - [Vagrantfile](https://github.com/commercialhaskell/stack/tree/master/etc/vagrant/centos-7-x86_64)) -* Upload Arch Linux packages (manual process) -* Build new MinGHC distribution (See https://github.com/fpco/minghc/commit/51490f398e6722672364548a3855a0bfcba48ffe) +Full details of prerequisites and steps for building MinGHC are in its +[README](https://github.com/fpco/minghc#building-installers). What follows is an +abbreviated set specifically for including the latest stack version. -After binaries uploaded: +* Ensure `makensis.exe` and `signtool.exe` are on your PATH. +* If you edit build-post-install.hs, run `stack exec -- cmd /c build-post-install.bat` +* Set `STACKVER` environment variable to latest Stack verion (e.g. `0.1.6.0`) +* Adjust commands below for new GHC versions +* Run: -* Push signed Git tag (matching Github release tag name). -* Publish Github release. -* Upload package to Hackage. -* Announce to haskell-cafe, commercialhaskell, and haskell-stack mailing lists. +``` +stack build +stack exec -- minghc-generate 7.10.2 --stack=%STACKVER% +signtool sign /v /n "FP Complete, Corporation" /t "http://timestamp.verisign.com/scripts/timestamp.dll" .build\minghc-7.10.2-i386.exe +stack exec -- minghc-generate 7.10.2 --arch64 --stack=%STACKVER% +signtool sign /v /n "FP Complete, Corporation" /t "http://timestamp.verisign.com/scripts/timestamp.dll" .build\minghc-7.10.2-x86_64.exe +stack exec -- minghc-generate 7.8.4 --stack=%STACKVER% +signtool sign /v /n "FP Complete, Corporation" /t "http://timestamp.verisign.com/scripts/timestamp.dll" .build\minghc-7.8.4-i386.exe +stack exec -- minghc-generate 7.8.4 --arch64 --stack=%STACKVER% +signtool sign /v /n "FP Complete, Corporation" /t "http://timestamp.verisign.com/scripts/timestamp.dll" .build\minghc-7.8.4-x86_64.exe +``` -For more information, see: https://github.com/commercialhaskell/stack/issues/324 +* Upload the build binaries to a new Github release +* Edit [README.md](https://github.com/fpco/minghc/blob/master/README.md#using-the-installer) and update download links diff --git a/etc/scripts/README.md b/etc/scripts/README.md index 6bd5500a16..dd00366faa 100644 --- a/etc/scripts/README.md +++ b/etc/scripts/README.md @@ -60,12 +60,18 @@ To create and upload Arch packages, you need: Building -------- - (cd etc/scripts && stack build) +Ensure that `~/.local/bin` is in your PATH, then: + + (cd etc/scripts && stack install) + +(note: do not use `stack exec stack-release-script`, because certain parts of +the build do not work properly while in a `stack exec` context, especially on +Windows) Invocation ---------- -Usage: `$(cd etc/scripts && stack exec which stack-release-script) [OPTIONS] TARGET` +Usage: `stack-release-script [OPTIONS] TARGET` The tool must be run in the root of the working tree. diff --git a/etc/scripts/osx-release.sh b/etc/scripts/osx-release.sh new file mode 100755 index 0000000000..b4dcdbd594 --- /dev/null +++ b/etc/scripts/osx-release.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +#TODO: move this logic into release.hs. +set -xe +RELEASE_SCRIPT=.local/bin/stack-release-script +rm -f "$RELEASE_SCRIPT" +(cd etc/scripts && stack build) +$(cd etc/scripts && stack exec which stack-release-script) --arch=x86_64 --upload-label="Mac OS X 64-bit" release diff --git a/etc/scripts/vagrant-distros.sh b/etc/scripts/vagrant-distros.sh new file mode 120000 index 0000000000..638a0aebfc --- /dev/null +++ b/etc/scripts/vagrant-distros.sh @@ -0,0 +1 @@ +vagrant-releases.sh \ No newline at end of file diff --git a/etc/scripts/vagrant-releases.sh b/etc/scripts/vagrant-releases.sh new file mode 100755 index 0000000000..da566734a5 --- /dev/null +++ b/etc/scripts/vagrant-releases.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +#TODO: move this logic into release.hs. +set -xe +init_wd="$(pwd)" + +with_vagrant() { + #TODO: set up gpg-agent forwarding for package signing (see http://superuser.com/questions/161973/how-can-i-forward-a-gpg-key-via-ssh-agent). + pushd "$init_wd/etc/vagrant/$1" + vagrant up --provision + vagrant rsync + vagrant ssh -c "export GITHUB_AUTH_TOKEN=$GITHUB_AUTH_TOKEN; export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID; export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY; export AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION; cd /vagrant && (cd etc/scripts && stack build) && \$(cd etc/scripts && stack exec which stack-release-script) $2" + vagrant halt + popd +} + +if [[ "$(basename "$0")" == "vagrant-releases.sh" ]]; then + with_vagrant debian-7-amd64 "--upload-label='Linux 64-bit, standard' release" + with_vagrant debian-7-i386 "--upload-label='Linux 32-bit, standard' release" + with_vagrant centos-6-x86_64 "--binary-variant=gmp4 --upload-label='Linux 64-bit, libgmp4 for CentOS 6.x' release" + with_vagrant centos-6-i386 "--binary-variant=gmp4 --upload-label='Linux 32-bit, libgmp4 for CentOS 6.x' release" +elif [[ "$(basename "$0")" == "vagrant-distros.sh" ]]; then + with_vagrant debian-7-amd64 "upload-ubuntu-12.04 upload-ubuntu-14.04 upload-ubuntu-14.10 upload-ubuntu-15.04 upload-ubuntu-15.10 upload-debian-7 upload-debian-8 upload-arch" + with_vagrant centos-7-x86_64 "upload-centos-7 upload-fedora-21 upload-fedora-22" + with_vagrant centos-6-x86_64 "--binary-variant=gmp4 upload-centos-6" +else + echo "Unknown script name: $(basename "$0")" >&2 + exit 1 +fi diff --git a/etc/scripts/windows-releases.bat b/etc/scripts/windows-releases.bat new file mode 100644 index 0000000000..0cfde40d37 --- /dev/null +++ b/etc/scripts/windows-releases.bat @@ -0,0 +1,16 @@ +REM TODO: move this logic into release.hs +setlocal +path C:\Program Files\Git\usr\bin;%PATH% +set STACK_ROOT=C:\.stack +set TMP=C:\tmp +set TEMP=C:\tmp +set RELEASE_SCRIPT=%APPDATA%\local\bin\stack-release-script.exe +if exist %RELEASE_SCRIPT% del %RELEASE_SCRIPT% +cd etc\scripts +stack install +if errorlevel 1 exit /b +cd ..\.. +%RELEASE_SCRIPT% --arch=i386 --upload-label="Windows 32-bit" release +if errorlevel 1 exit /b +%RELEASE_SCRIPT% --arch=x86_64 --upload-label="Windows 64-bit" release +if errorlevel 1 exit /b diff --git a/etc/vagrant/centos-6-i386/Vagrantfile b/etc/vagrant/centos-6-i386/Vagrantfile index b18b155615..94190c20ff 100644 --- a/etc/vagrant/centos-6-i386/Vagrantfile +++ b/etc/vagrant/centos-6-i386/Vagrantfile @@ -6,18 +6,17 @@ Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = "2048" end - config.vm.provision "shell", run: "always", inline: <<-SHELL + config.ssh.forward_agent = true + config.vm.provision "shell", inline: <<-SHELL set -xe export PATH=/usr/local/bin:$PATH + yum update yum -y install perl make automake gcc gmp-devel zlib-devel tar which git xz ncurses-devel - if ! which stack; then - curl -sSL $(curl -sSL https://api.github.com/repos/commercialhaskell/stack/releases/latest \ - |grep '"browser_download_url": ".*/stack-[0-9\\.]\\+-i386-linux-gmp4.gz"' \ - |sed 's/.*"\\(.*\\)"$/\\1/') \ - | gzip -dc \ - >/usr/local/bin/stack - chmod a+x /usr/local/bin/stack - fi + curl -sSL $(curl -sSL https://api.github.com/repos/commercialhaskell/stack/releases/latest \ + | grep '"browser_download_url": ".*/stack-.*-i386-linux-gmp4.tar.gz"' \ + | sed 's/.*"\(.*\)"$/\1/') \ + | tar xzvf - --wildcards --strip-components=1 -C /usr/local/bin '*/stack' + chmod a+x /usr/local/bin/stack if ! which cabal; then pushd /vagrant stack --install-ghc install cabal-install diff --git a/etc/vagrant/centos-6-x86_64/Vagrantfile b/etc/vagrant/centos-6-x86_64/Vagrantfile index 0e09e7b5d3..c12516b480 100644 --- a/etc/vagrant/centos-6-x86_64/Vagrantfile +++ b/etc/vagrant/centos-6-x86_64/Vagrantfile @@ -6,15 +6,18 @@ Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = "2048" end - config.vm.provision "shell", run: "always", inline: <<-SHELL + config.ssh.forward_agent = true + config.vm.provision "shell", inline: <<-SHELL set -xe export PATH=/usr/local/bin:$PATH + yup update yum -y install epel-release yum -y install perl make automake gcc gmp-devel zlib-devel rpm-build tar which git xz python-boto deltarpm python-deltarpm rpm-build rpm-sign ncurses-devel - if ! [[ -f /usr/local/bin/stack ]]; then + if ! which stack; then curl -sSL https://s3.amazonaws.com/download.fpcomplete.com/centos/6/fpco.repo >/etc/yum.repos.d/fpco.repo - yum -y install stack + yum update fi + yum -y install stack if ! which cabal; then stack --install-ghc build cabal-install cp `stack exec which cabal` /usr/local/bin/cabal diff --git a/etc/vagrant/centos-7-x86_64/Vagrantfile b/etc/vagrant/centos-7-x86_64/Vagrantfile index 8607133522..eaca3789d7 100644 --- a/etc/vagrant/centos-7-x86_64/Vagrantfile +++ b/etc/vagrant/centos-7-x86_64/Vagrantfile @@ -6,15 +6,18 @@ Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = "2048" end - config.vm.provision "shell", run: "always", inline: <<-SHELL + config.ssh.forward_agent = true + config.vm.provision "shell", inline: <<-SHELL set -xe export PATH=/usr/local/bin:$PATH + yup update yum -y install epel-release yum -y install perl make automake gcc gmp-devel zlib-devel tar which git python-boto deltarpm python-deltarpm rpm-build rpm-sign ncurses-devel - if ! [[ -f /usr/local/bin/stack ]]; then + if ! which stack; then curl -sSL https://s3.amazonaws.com/download.fpcomplete.com/centos/7/fpco.repo >/etc/yum.repos.d/fpco.repo - yum -y install stack + yum update fi + yum -y install stack if ! which cabal; then pushd /vagrant stack --install-ghc install cabal-install diff --git a/etc/vagrant/debian-7-amd64/Vagrantfile b/etc/vagrant/debian-7-amd64/Vagrantfile index 5d6f6ea64d..a5c5773c8b 100644 --- a/etc/vagrant/debian-7-amd64/Vagrantfile +++ b/etc/vagrant/debian-7-amd64/Vagrantfile @@ -6,7 +6,8 @@ Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = "2048" end - config.vm.provision "shell", run: "always", inline: <<-SHELL + config.ssh.forward_agent = true + config.vm.provision "shell", inline: <<-SHELL set -xe export PATH=/usr/local/bin:$PATH export DEBIAN_FRONTEND=noninteractive @@ -16,8 +17,8 @@ Vagrant.configure(2) do |config| wget -q -O- http://download.fpcomplete.com/ubuntu/fpco.key | apt-key add - echo "deb http://download.fpcomplete.com/debian/$(lsb_release -cs) stable main" >/etc/apt/sources.list.d/fpco.list apt-get update - apt-get install -y stack fi + apt-get install -y stack if ! which cabal; then stack --install-ghc build cabal-install sudo cp `stack exec which cabal` /usr/local/bin/cabal diff --git a/etc/vagrant/debian-7-i386/Vagrantfile b/etc/vagrant/debian-7-i386/Vagrantfile index ad713f9a8c..6bfc45fed1 100644 --- a/etc/vagrant/debian-7-i386/Vagrantfile +++ b/etc/vagrant/debian-7-i386/Vagrantfile @@ -6,37 +6,35 @@ Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = "2048" end - config.vm.provision "shell", run: "always", inline: <<-SHELL + config.ssh.forward_agent = true + config.vm.provision "shell", inline: <<-SHELL set -xe export PATH=/usr/local/bin:$PATH export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y net-tools wget zlib1g-dev ruby-dev libgmp-dev lsb-release ca-certificates git libtinfo-dev - if ! which stack; then - curl -sSL $(curl -sSL https://api.github.com/repos/commercialhaskell/stack/releases/latest \ - |grep '"browser_download_url": ".*/stack-[0-9\\.]\\+-i386-linux.gz"' \ - |sed 's/.*"\\(.*\\)"$/\\1/') \ - | gzip -dc \ - >/usr/local/bin/stack - chmod a+x /usr/local/bin/stack - fi + curl -sSL $(curl -sSL https://api.github.com/repos/commercialhaskell/stack/releases/latest \ + | grep '"browser_download_url": ".*/stack-.*-i386-linux.tar.gz"' \ + | sed 's/.*"\(.*\)"$/\1/') \ + | tar xzvf - --wildcards --strip-components=1 -C /usr/local/bin '*/stack' + chmod a+x /usr/local/bin/stack if ! which cabal; then stack --install-ghc build cabal-install cp `stack exec which cabal` /usr/local/bin/cabal fi if ! which fpm; then - apt-get install -y ruby-dev libffi-dev make build-essential - apt-get install -y rubygems || true - gem install fpm --version '< 1.4.0' + apt-get install -y ruby-dev libffi-dev make build-essential + apt-get install -y rubygems || true + gem install fpm --version '< 1.4.0' fi if ! which deb-s3; then - gem install deb-s3 + gem install deb-s3 fi if ! which aws; then - apt-get install -y python2.7 - curl -O https://bootstrap.pypa.io/get-pip.py - sudo python2.7 get-pip.py - sudo pip install awscli + apt-get install -y python2.7 + curl -O https://bootstrap.pypa.io/get-pip.py + sudo python2.7 get-pip.py + sudo pip install awscli fi SHELL end From 78e5871d3514b54c997a0d54e23fcf0096c73be6 Mon Sep 17 00:00:00 2001 From: Kostiantyn Rybnikov Date: Fri, 16 Oct 2015 11:40:03 +0300 Subject: [PATCH 028/106] Add brew-based install --- doc/install_and_upgrade.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index 7d4818bc64..16fec26139 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -14,6 +14,16 @@ NOTE: These executables have been built and tested on a Windows 7, 8.1, and 10 6 ## OS X +### Using brew + +If you have a popular [brew](http://brew.sh/) tool installed, you can just do: + +``` +brew install haskell-stack +``` + +### Manual download + * Download [the latest release](https://github.com/commercialhaskell/stack/releases/latest) * Extract the archive and place `stack` somewhere on your `$PATH` (see [Path section below](#path)) * Now you can run `stack` from the terminal. From dc8607980f5f9afb50defccf35071ed68b55029a Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 04:38:51 -0700 Subject: [PATCH 029/106] Upper bounds on aeson and attoparsec, to relax --pvp-bounds --- stack.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stack.cabal b/stack.cabal index a8c6a02c4b..e5cc9dc5c2 100644 --- a/stack.cabal +++ b/stack.cabal @@ -119,10 +119,10 @@ library Data.Set.Monad Distribution.Version.Extra build-depends: Cabal >= 1.18.1.5 - , aeson >= 0.8.0.2 + , aeson >= 0.8.0.2 && < 0.10 , ansi-terminal >= 0.6.2.3 , async >= 2.0.2 - , attoparsec >= 0.12.1.5 + , attoparsec >= 0.12.1.5 && < 0.14 , base >= 4 && <5 , base16-bytestring , base64-bytestring From d916387e57dd45f3c3d49ea48df0ba4ce7733eb4 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 04:43:29 -0700 Subject: [PATCH 030/106] Set rebuild-ghc-options for integration test 796-ghc-options --- test/integration/tests/796-ghc-options/files/stack.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/tests/796-ghc-options/files/stack.yaml b/test/integration/tests/796-ghc-options/files/stack.yaml index 0a78d1258d..a573a9a79b 100644 --- a/test/integration/tests/796-ghc-options/files/stack.yaml +++ b/test/integration/tests/796-ghc-options/files/stack.yaml @@ -3,3 +3,4 @@ ghc-options: "*": -DFOO ghc-options: -DBAR text: -DBAZ +rebuild-ghc-options: true From b2e230a66296acc493878d79e93666fabfba30d9 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 05:14:12 -0700 Subject: [PATCH 031/106] release.hs: check 'stack --version' for dirtiness, and always use '--install-ghc' --- etc/scripts/release.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/etc/scripts/release.hs b/etc/scripts/release.hs index 3362c2feca..943675eb86 100644 --- a/etc/scripts/release.hs +++ b/etc/scripts/release.hs @@ -186,6 +186,10 @@ rules global@Global{..} args = do releaseDir binaryExeFileName %> \out -> do need [releaseBinDir binaryName stackExeFileName] + (Stdout versionOut) <- cmd (releaseBinDir binaryName stackExeFileName) "--version" + when (not gAllowDirty && "dirty" `isInfixOf` lower versionOut) $ + error ("Refusing continue because 'stack --version' reports dirty. Use --" ++ + allowDirtyOptName ++ " option to continue anyway.") case platformOS of Windows -> do -- Windows doesn't have or need a 'strip' command, so skip it. @@ -221,7 +225,7 @@ rules global@Global{..} args = do (cmd stackProgName (stackArgs global) ["--local-bin-path=" ++ takeDirectory out] - "--install-ghc install --pedantic") + "install --pedantic") (removeFile out) debDistroRules ubuntuDistro ubuntuVersions @@ -604,7 +608,7 @@ uploadLabelOptName = "upload-label" -- | Arguments to pass to all 'stack' invocations. stackArgs :: Global -> [String] -stackArgs Global{..} = ["--arch=" ++ display gArch] +stackArgs Global{..} = ["--install-ghc", "--arch=" ++ display gArch] -- | Name of the 'stack' program. stackProgName :: FilePath From adda7d9facc38283648bef074f372c1cf7311388 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 05:14:32 -0700 Subject: [PATCH 032/106] MAINTAINERS_GUIDE: update --- doc/MAINTAINER_GUIDE.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/doc/MAINTAINER_GUIDE.md b/doc/MAINTAINER_GUIDE.md index 5f8861d639..e5eaf08008 100644 --- a/doc/MAINTAINER_GUIDE.md +++ b/doc/MAINTAINER_GUIDE.md @@ -57,12 +57,11 @@ for requirements to perform the release, and more details about the tool. * Upload package to Hackage: `stack upload . --pvp-bounds=both` - Note: due to a - Cabal pretty-printer bug, this may fail with a syntax error. If so, use - `stack upload .`, then run `stack sdist --pvp-bounds=both`, and use - Hackage's - [edit package information](http://hackage.haskell.org/package/stack/maintain) - feature to paste the bounds in from the sdist's `stack.cabal`. + Note: due to a Cabal pretty-printer bug, this may fail with a syntax error. + This bug is fixed in Cabal HEAD. Can also work around it by running `stack + sdist --pvp-bounds=both`, updating `stack.cabal`'s bounds from the sdist's + version, then uploading with `stack upload .`. Don't forget to undo the change to + `stack.cabal` afterward (don't commit it). * On a machine with Vagrant installed: * Run `etc/scripts/vagrant-distros.sh` @@ -74,7 +73,9 @@ for requirements to perform the release, and more details about the tool. * Submit a PR for the [haskell-stack Homebrew formula](https://github.com/Homebrew/homebrew/blob/master/Library/Formula/haskell-stack.rb). - The commit message should just be `haskell-stack `. + The commit message should just be `haskell-stack ` + * Note: for v0.1.8.0, check if `pcre` should still be a dependency + * Also, update the homepage * [Build new MinGHC distribution](#build_minghc) @@ -84,7 +85,7 @@ for requirements to perform the release, and more details about the tool. # Extra steps -## Upload haddocks to Hackage +## Upload haddocks to Hackage * Set `STACKVER` environment variable to the Stack version (e.g. `0.1.6.0`) * Run: @@ -104,7 +105,7 @@ curl -X PUT \ "https://hackage.haskell.org/package/stack-$STACKVER/docs" ``` -## Build MinGHC +## Update MinGHC Full details of prerequisites and steps for building MinGHC are in its [README](https://github.com/fpco/minghc#building-installers). What follows is an @@ -128,5 +129,5 @@ stack exec -- minghc-generate 7.8.4 --arch64 --stack=%STACKVER% signtool sign /v /n "FP Complete, Corporation" /t "http://timestamp.verisign.com/scripts/timestamp.dll" .build\minghc-7.8.4-x86_64.exe ``` -* Upload the build binaries to a new Github release +* Upload the built binaries to a new Github release * Edit [README.md](https://github.com/fpco/minghc/blob/master/README.md#using-the-installer) and update download links From 362c10374fa4669d4cc6aeb1b825d29620b2752c Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 06:30:26 -0700 Subject: [PATCH 033/106] install_and_upgrade.md: link to https://www.stackage.org/stack --- doc/install_and_upgrade.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index 16fec26139..579d9aca5f 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -1,7 +1,16 @@ -Distribution packages are available for [Ubuntu](#ubuntu), [Debian](#debian), [CentOS / Red Hat](#centos--red-hat), [Fedora](#fedora) and [Arch Linux](#arch-linux). Binaries for other operating systems are available on [the releases page](https://github.com/fpco/stack/releases). For the future, we have plans to support more OSes. +Distribution packages are available for [Ubuntu](#ubuntu), [Debian](#debian), +[CentOS / Red Hat](#centos--red-hat), [Fedora](#fedora) and +[Arch Linux](#arch-linux). Binaries for other operating systems are available on +[the releases page](https://github.com/fpco/stack/releases). For the future, we +are open to supporting more OSes (to request one, please +[submit an issue](https://github.com/commercialhaskell/stack/issues/new)). Binary packages are signed with this [signing key](SIGNING_KEY.md). +If you are writing a script that needs to download the latest binary, you can +find links that always point to the latest bindists +[here](https://www.stackage.org/stack). + ## Windows *Note*: Due to specific Windows limitations, [some temporary workarounds](https://www.fpcomplete.com/blog/2015/08/stack-ghc-windows) may be required. It is strongly advised to set your `STACK_ROOT` environment variable similarly to your root (e.g., `set STACK_ROOT=c:\stack_root`) *before* running `stack`. From 479b40f79922bbdb430218babec334c22c185562 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 06:33:17 -0700 Subject: [PATCH 034/106] Update release process with https://www.stackage.org/stack links --- doc/MAINTAINER_GUIDE.md | 3 +++ etc/vagrant/centos-6-i386/Vagrantfile | 4 +--- etc/vagrant/debian-7-i386/Vagrantfile | 4 +--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/MAINTAINER_GUIDE.md b/doc/MAINTAINER_GUIDE.md index e5eaf08008..32b3072553 100644 --- a/doc/MAINTAINER_GUIDE.md +++ b/doc/MAINTAINER_GUIDE.md @@ -55,6 +55,9 @@ for requirements to perform the release, and more details about the tool. [stack-setup-2.yaml](https://github.com/fpco/stackage-content/blob/master/stack/stack-setup-2.yaml), and add the new linux64 stack bindist +* Check that no new entries need to be added to + [releases.yaml](https://github.com/fpco/stackage-content/blob/master/stack/releases.yaml) + * Upload package to Hackage: `stack upload . --pvp-bounds=both` Note: due to a Cabal pretty-printer bug, this may fail with a syntax error. diff --git a/etc/vagrant/centos-6-i386/Vagrantfile b/etc/vagrant/centos-6-i386/Vagrantfile index 94190c20ff..fa672b8ba0 100644 --- a/etc/vagrant/centos-6-i386/Vagrantfile +++ b/etc/vagrant/centos-6-i386/Vagrantfile @@ -12,9 +12,7 @@ Vagrant.configure(2) do |config| export PATH=/usr/local/bin:$PATH yum update yum -y install perl make automake gcc gmp-devel zlib-devel tar which git xz ncurses-devel - curl -sSL $(curl -sSL https://api.github.com/repos/commercialhaskell/stack/releases/latest \ - | grep '"browser_download_url": ".*/stack-.*-i386-linux-gmp4.tar.gz"' \ - | sed 's/.*"\(.*\)"$/\1/') \ + curl -sSL https://www.stackage.org/stack/linux-i386-gmp4 \ | tar xzvf - --wildcards --strip-components=1 -C /usr/local/bin '*/stack' chmod a+x /usr/local/bin/stack if ! which cabal; then diff --git a/etc/vagrant/debian-7-i386/Vagrantfile b/etc/vagrant/debian-7-i386/Vagrantfile index 6bfc45fed1..89377eba54 100644 --- a/etc/vagrant/debian-7-i386/Vagrantfile +++ b/etc/vagrant/debian-7-i386/Vagrantfile @@ -13,9 +13,7 @@ Vagrant.configure(2) do |config| export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y net-tools wget zlib1g-dev ruby-dev libgmp-dev lsb-release ca-certificates git libtinfo-dev - curl -sSL $(curl -sSL https://api.github.com/repos/commercialhaskell/stack/releases/latest \ - | grep '"browser_download_url": ".*/stack-.*-i386-linux.tar.gz"' \ - | sed 's/.*"\(.*\)"$/\1/') \ + curl -sSL https://www.stackage.org/stack/linux-i386 \ | tar xzvf - --wildcards --strip-components=1 -C /usr/local/bin '*/stack' chmod a+x /usr/local/bin/stack if ! which cabal; then From 891ba6fa4583cb3da3214f4388f6e8eb3b7a1ef2 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 09:54:23 -0700 Subject: [PATCH 035/106] install_and_upgrade.md: Use www.stackage.org/stack download links --- doc/install_and_upgrade.md | 48 ++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index 579d9aca5f..a288de0b72 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -1,8 +1,9 @@ Distribution packages are available for [Ubuntu](#ubuntu), [Debian](#debian), [CentOS / Red Hat](#centos--red-hat), [Fedora](#fedora) and -[Arch Linux](#arch-linux). Binaries for other operating systems are available on -[the releases page](https://github.com/fpco/stack/releases). For the future, we -are open to supporting more OSes (to request one, please +[Arch Linux](#arch-linux). Binaries for other operating systems are listed +below, and available on +[the Github releases page](https://github.com/fpco/stack/releases). For the +future, we are open to supporting more OSes (to request one, please [submit an issue](https://github.com/commercialhaskell/stack/issues/new)). Binary packages are signed with this [signing key](SIGNING_KEY.md). @@ -15,11 +16,25 @@ find links that always point to the latest bindists *Note*: Due to specific Windows limitations, [some temporary workarounds](https://www.fpcomplete.com/blog/2015/08/stack-ghc-windows) may be required. It is strongly advised to set your `STACK_ROOT` environment variable similarly to your root (e.g., `set STACK_ROOT=c:\stack_root`) *before* running `stack`. -* Download [the latest release](https://github.com/commercialhaskell/stack/releases/latest). Note: while generally i386/32-bit GHC is better tested on Windows, there are reports that recent versions of Windows only work with the 64-bit version of stack (see [issue #393](https://github.com/commercialhaskell/stack/issues/393)). -* Unpack the archive and place `stack.exe` somewhere on your `%PATH%` (see [Path section below](#path)) and you can then run `stack` on the command line. +* Download the latest release: + + * [Windows 32-bit](https://www.stackage.org/stack/windows-i386) + * [Windows 64-bit](https://www.stackage.org/stack/windows-x86_64) + + Note: while generally 32-bit GHC is better tested on Windows, there are + reports that recent versions of Windows only work with the 64-bit version of + stack (see + [issue #393](https://github.com/commercialhaskell/stack/issues/393)). + +* Unpack the archive and place `stack.exe` somewhere on your `%PATH%` (see + [Path section below](#path)) and you can then run `stack` on the command line. + * Now you can run `stack` from the terminal. -NOTE: These executables have been built and tested on a Windows 7, 8.1, and 10 64-bit machines. They should run on older Windows installs as well, but have not been tested. If you do test, please edit and update this page to indicate as such. +NOTE: These executables have been built and tested on a Windows 7, 8.1, and 10 +64-bit machines. They should run on older Windows installs as well, but have not +been tested. If you do test, please edit and update this page to indicate as +such. ## OS X @@ -33,11 +48,14 @@ brew install haskell-stack ### Manual download -* Download [the latest release](https://github.com/commercialhaskell/stack/releases/latest) -* Extract the archive and place `stack` somewhere on your `$PATH` (see [Path section below](#path)) +* Download the latest release: + * [Mac OS X 64-bit](https://www.stackage.org/stack/osx-x86_64) +* Extract the archive and place `stack` somewhere on your `$PATH` (see + [Path section below](#path)) * Now you can run `stack` from the terminal. -We generally test on the current version of OS X, but stack is known to work on Mavericks as well, and may also work on older versions (YMMV). +We generally test on the current version of OS X, but stack is known to work on +Yosemite and Mavericks as well, and may also work on older versions (YMMV). ## Ubuntu @@ -181,8 +199,18 @@ Stack](http://nixos.org/nixpkgs/manual/#using-stack-together-with-nix). (64-bit and 32-bit options available) -* Download [the latest release](https://github.com/commercialhaskell/stack/releases/latest). Note: the `-gmp4` variants are for older distributions (such as CentOS 6.x) that only include libgmp4 (libgmp.so.3). +* Download the latest release: + + * [Linux 64-bit, standard](https://www.stackage.org/stack/linux-x86_64) + * [Linux 32-bit, standard](https://www.stackage.org/stack/linux-i386) + + If you are on an older distribution that only includes libgmp4 (libgmp.so.3), Such as CentOS/RHEL/Amazon Linux 6.x, use one of these instead: + + * [Linux 64-bit, libgmp4](https://www.stackage.org/stack/linux-x86_64-gmp4) + * [Linux 32-bit, libgmp4](https://www.stackage.org/stack/linux-i386-gmp4) + * Extract the archive and place `stack` somewhere on your `$PATH` (see [Path section below](#path)) + * Now you can run `stack` from the terminal. Tested on Fedora 20: make sure to install the following packages `sudo yum install perl make automake gcc gmp-devel`. From 44f686b11e27006097166b64f45447e0c7592020 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 09:59:26 -0700 Subject: [PATCH 036/106] docs: minor edits --- README.md | 2 +- doc/install_and_upgrade.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cbf259ef60..45935ad999 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ It features: Downloads are available by operating system: * [Windows](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#windows) -* [OS X](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#os-x) +* [Mac OS X](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#mac-os-x) * [Ubuntu](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#ubuntu) * [Debian](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#debian) * [CentOS / Red Hat / Amazon Linux](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#centos--red-hat--amazon-linux) diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index a288de0b72..192473f3fa 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -36,7 +36,7 @@ NOTE: These executables have been built and tested on a Windows 7, 8.1, and 10 been tested. If you do test, please edit and update this page to indicate as such. -## OS X +## Mac OS X ### Using brew @@ -54,7 +54,7 @@ brew install haskell-stack [Path section below](#path)) * Now you can run `stack` from the terminal. -We generally test on the current version of OS X, but stack is known to work on +We generally test on the current version of Mac OS X, but stack is known to work on Yosemite and Mavericks as well, and may also work on older versions (YMMV). ## Ubuntu @@ -204,7 +204,7 @@ Stack](http://nixos.org/nixpkgs/manual/#using-stack-together-with-nix). * [Linux 64-bit, standard](https://www.stackage.org/stack/linux-x86_64) * [Linux 32-bit, standard](https://www.stackage.org/stack/linux-i386) - If you are on an older distribution that only includes libgmp4 (libgmp.so.3), Such as CentOS/RHEL/Amazon Linux 6.x, use one of these instead: + If you are on an older distribution that only includes libgmp4 (libgmp.so.3), such as CentOS/RHEL/Amazon Linux 6.x, use one of these instead: * [Linux 64-bit, libgmp4](https://www.stackage.org/stack/linux-x86_64-gmp4) * [Linux 32-bit, libgmp4](https://www.stackage.org/stack/linux-i386-gmp4) From 8346914d9d734f6bbb42465c7fe393c37b9317fb Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Fri, 16 Oct 2015 19:37:38 -0700 Subject: [PATCH 037/106] install_and_upgrade.md: add Windows installers (#613) --- doc/install_and_upgrade.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index 192473f3fa..80c08136c2 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -14,7 +14,11 @@ find links that always point to the latest bindists ## Windows -*Note*: Due to specific Windows limitations, [some temporary workarounds](https://www.fpcomplete.com/blog/2015/08/stack-ghc-windows) may be required. It is strongly advised to set your `STACK_ROOT` environment variable similarly to your root (e.g., `set STACK_ROOT=c:\stack_root`) *before* running `stack`. +*Note*: Due to specific Windows limitations, + [some temporary workarounds](https://www.fpcomplete.com/blog/2015/08/stack-ghc-windows) + may be required. It is strongly advised to set your `STACK_ROOT` environment + variable similarly to your root (e.g., `set STACK_ROOT=c:\stack_root`) *before* + running `stack`. * Download the latest release: @@ -36,6 +40,14 @@ NOTE: These executables have been built and tested on a Windows 7, 8.1, and 10 been tested. If you do test, please edit and update this page to indicate as such. +### Installer (experimental) + +We recommend installing to the default location with these installers, as that +will make `stack install` and `stack upgrade` work correctly out of the box. + + * [Windows 32-bit Installer](https://www.stackage.org/stack/windows-i386-installer) (experimental) + * [Windows 64-bit Installer](https://www.stackage.org/stack/windows-x86_64-installer) (experimental) + ## Mac OS X ### Using brew From 0912e63f3f3c8e1ecf14e10a6ff967a6e01208d7 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sat, 17 Oct 2015 06:04:15 -0700 Subject: [PATCH 038/106] Document Windows installers --- ChangeLog.md | 3 +++ doc/MAINTAINER_GUIDE.md | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 620066b22a..ecdec0c0cc 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,9 @@ Major changes: +* Windows installers are now available: + [download them here](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#windows) [#613](https://github.com/commercialhaskell/stack/issues/613) + Other enhancements: * Added an `allow-newer` config option [#922](https://github.com/commercialhaskell/stack/issues/922) [#770](https://github.com/commercialhaskell/stack/issues/770) diff --git a/doc/MAINTAINER_GUIDE.md b/doc/MAINTAINER_GUIDE.md index 32b3072553..7212a734e7 100644 --- a/doc/MAINTAINER_GUIDE.md +++ b/doc/MAINTAINER_GUIDE.md @@ -20,6 +20,11 @@ to go: * Ensure all `doc/*.md` files are listed in `stack.cabal`'s 'extra-source-files` * Check that any new Linux distribution versions added to `etc/scripts/release.hs` and `etc/scripts/vagrant-releases.sh` +* Check that no new entries need to be added to + [releases.yaml](https://github.com/fpco/stackage-content/blob/master/stack/releases.yaml), + [install_and_upgrade.md](https://github.com/commercialhaskell/stack/blob/master/doc/install_and_upgrade.md), + and + [README.md](https://github.com/commercialhaskell/stack/blob/master/README.md) ## Release process @@ -55,9 +60,6 @@ for requirements to perform the release, and more details about the tool. [stack-setup-2.yaml](https://github.com/fpco/stackage-content/blob/master/stack/stack-setup-2.yaml), and add the new linux64 stack bindist -* Check that no new entries need to be added to - [releases.yaml](https://github.com/fpco/stackage-content/blob/master/stack/releases.yaml) - * Upload package to Hackage: `stack upload . --pvp-bounds=both` Note: due to a Cabal pretty-printer bug, this may fail with a syntax error. @@ -80,6 +82,8 @@ for requirements to perform the release, and more details about the tool. * Note: for v0.1.8.0, check if `pcre` should still be a dependency * Also, update the homepage +* Build Windows installers. See https://github.com/borsboom/stack-installer#readme + * [Build new MinGHC distribution](#build_minghc) * [Upload haddocks to Hackage](#upload_haddocks), if hackage couldn't build on its own From 8070fc84b92710947e8fedb1bbfea7891f5c0cd0 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sat, 17 Oct 2015 20:03:52 +0200 Subject: [PATCH 039/106] Use NonEmpty in return type of fuzzyLookupCandidates --- src/Stack/Fetch.hs | 12 +++++++----- stack.cabal | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Stack/Fetch.hs b/src/Stack/Fetch.hs index b82ed84c30..98139a803c 100644 --- a/src/Stack/Fetch.hs +++ b/src/Stack/Fetch.hs @@ -50,7 +50,9 @@ import qualified Data.Foldable as F import Data.Function (fix) import Data.IORef (newIORef, readIORef, writeIORef) -import Data.List (intercalate, intersperse) +import Data.List (intercalate) +import Data.List.NonEmpty (NonEmpty) +import qualified Data.List.NonEmpty as NonEmpty import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (maybeToList, catMaybes) @@ -312,7 +314,8 @@ withCabalLoader menv inner = do inner doLookup where unknownIdent = UnknownPackageIdentifiers . Set.singleton - commaSeparatedIdents = F.fold . intersperse ", " . map packageIdentifierString + commaSeparatedIdents = + F.fold . NonEmpty.intersperse ", " . NonEmpty.map packageIdentifierString type PackageCaches = Map PackageIdentifier (PackageIndex, PackageCache) @@ -328,11 +331,10 @@ lookupPackageIdentifierExact ident env caches = do $ \_ _ bs -> return bs return $ Just bs --- TODO: use 'Maybe (NonEmpty PackageIdentifier)' return-type fuzzyLookupCandidates :: PackageIdentifier -> PackageCaches - -> Maybe [PackageIdentifier] + -> Maybe (NonEmpty PackageIdentifier) fuzzyLookupCandidates (PackageIdentifier name ver) caches = - if null sameMajor then Nothing else Just (map fst sameMajor) + NonEmpty.nonEmpty (map fst sameMajor) where sameMajor = filter (\(PackageIdentifier _ v, _) -> toMajorVersion ver == toMajorVersion v) diff --git a/stack.cabal b/stack.cabal index 78bb375ef8..4cceaefb80 100644 --- a/stack.cabal +++ b/stack.cabal @@ -170,6 +170,7 @@ library , resourcet >= 1.1.4.1 , retry >= 0.6 , safe >= 0.3 + , semigroups >= 0.5 , split , stm >= 2.4.4 , streaming-commons >= 0.1.10.0 From 9dc967b2ea673f16fa15544ce40626bc5583c9fb Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Sat, 17 Oct 2015 19:55:32 +0000 Subject: [PATCH 040/106] Increased upper bound on vector package --- stack.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.cabal b/stack.cabal index 78bb375ef8..3d1cb3493e 100644 --- a/stack.cabal +++ b/stack.cabal @@ -182,7 +182,7 @@ library , transformers-base >= 0.4.4 , unix-compat , unordered-containers >= 0.2.5.1 - , vector >= 0.10.12.3 + , vector >= 0.10.12.3 && < 0.12 , vector-binary-instances , void >= 0.7 , yaml >= 0.8.10.1 From 3a1de649c764d520bf959b0cfcdaa9cf8dc9e724 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sat, 17 Oct 2015 23:25:44 +0200 Subject: [PATCH 041/106] Remove redundant Version info from InstalledMap, LoadHelper and PackageInfo types --- src/Stack/Build/ConstructPlan.hs | 17 +++++++++-------- src/Stack/Build/Execute.hs | 2 +- src/Stack/Build/Installed.hs | 6 +++--- src/Stack/Dot.hs | 5 +---- src/Stack/Package.hs | 2 +- src/Stack/SDist.hs | 2 +- src/Stack/Types/Package.hs | 7 ++++++- 7 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 86f112b357..3b2e47ef0d 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -47,19 +47,19 @@ import Stack.PackageIndex import Stack.Types data PackageInfo - = PIOnlyInstalled Version InstallLocation Installed + = PIOnlyInstalled InstallLocation Installed | PIOnlySource PackageSource | PIBoth PackageSource Installed combineSourceInstalled :: PackageSource - -> (Version, InstallLocation, Installed) + -> (InstallLocation, Installed) -> PackageInfo -combineSourceInstalled ps (version, location, installed) = - assert (piiVersion ps == version) $ +combineSourceInstalled ps (location, installed) = + assert (piiVersion ps == installedVersion installed) $ assert (piiLocation ps == location) $ case location of -- Always trust something in the snapshot - Snap -> PIOnlyInstalled version location installed + Snap -> PIOnlyInstalled location installed Local -> PIBoth ps installed type CombinedMap = Map PackageName PackageInfo @@ -68,7 +68,7 @@ combineMap :: SourceMap -> InstalledMap -> CombinedMap combineMap = Map.mergeWithKey (\_ s i -> Just $ combineSourceInstalled s i) (fmap PIOnlySource) - (fmap (\(v, l, i) -> PIOnlyInstalled v l i)) + (fmap (\(l, i) -> PIOnlyInstalled l i)) data AddDepRes = ADRToInstall Task @@ -282,7 +282,8 @@ addDep'' treatAsDep name = do -- TODO look up in the package index and see if there's a -- recommendation available Nothing -> return $ Left $ UnknownPackage name - Just (PIOnlyInstalled version loc installed) -> do + Just (PIOnlyInstalled loc installed) -> do + let version = installedVersion installed tellExecutablesUpstream name version loc Map.empty -- slightly hacky, no flags since they likely won't affect executable names return $ Right $ ADRFound loc version installed Just (PIOnlySource ps) -> do @@ -316,7 +317,7 @@ tellExecutablesPackage loc p = do let myComps = case Map.lookup (packageName p) cm of Nothing -> assert False Set.empty - Just (PIOnlyInstalled _ _ _) -> Set.empty + Just (PIOnlyInstalled _ _) -> Set.empty Just (PIOnlySource ps) -> goSource ps Just (PIBoth ps _) -> goSource ps diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 4ae6844c44..69777a5d52 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1053,7 +1053,7 @@ depsPresent :: InstalledMap -> Map PackageName VersionRange -> Bool depsPresent installedMap deps = all (\(name, range) -> case Map.lookup name installedMap of - Just (version, _, _) -> version `withinRange` range + Just (_, installed) -> (installedVersion installed) `withinRange` range Nothing -> False) (Map.toList deps) diff --git a/src/Stack/Build/Installed.hs b/src/Stack/Build/Installed.hs index c3716e2f6b..c1b962453a 100644 --- a/src/Stack/Build/Installed.hs +++ b/src/Stack/Build/Installed.hs @@ -44,7 +44,7 @@ type M env m = (MonadIO m,MonadReader env m,HasHttpManager env,HasEnvConfig env, data LoadHelper = LoadHelper { lhId :: !GhcPkgId , lhDeps :: ![GhcPkgId] - , lhPair :: !(PackageName, (Version, InstallLocation, Installed)) -- TODO Version is now redundant and can be gleaned from Installed + , lhPair :: !(PackageName, (InstallLocation, Installed)) } deriving Show @@ -107,7 +107,7 @@ getInstalled menv opts sourceMap = do | otherwise -> m where - m = Map.singleton name (version, loc, Executable $ PackageIdentifier name version) + m = Map.singleton name (loc, Executable $ PackageIdentifier name version) exesSnap <- getInstalledExes Snap exesLocal <- getInstalledExes Local let installedMap = Map.unions @@ -194,7 +194,7 @@ isAllowed opts mcache sourceMap mloc dp if name `HashSet.member` wiredInPackages then [] else dpDepends dp - , lhPair = (name, (version, toPackageLocation mloc, Library ident gid)) + , lhPair = (name, (toPackageLocation mloc, Library ident gid)) } | otherwise = Nothing where diff --git a/src/Stack/Dot.hs b/src/Stack/Dot.hs index 6aae329abb..12f2f7a51c 100644 --- a/src/Stack/Dot.hs +++ b/src/Stack/Dot.hs @@ -92,7 +92,7 @@ createDependencyGraph dotOpts = do (_,_,locals,_,sourceMap) <- loadSourceMap NeedTargets defaultBuildOpts let graph = Map.fromList (localDependencies dotOpts locals) menv <- getMinimalEnvOverride - installedMap <- fmap thrd . fst3 <$> getInstalled menv + installedMap <- fmap snd . fst3 <$> getInstalled menv (GetInstalledOpts False False) sourceMap withLoadPackage menv (\loader -> do @@ -105,9 +105,6 @@ createDependencyGraph dotOpts = do fmap3 :: Functor f => (d -> e) -> (a -> b -> c -> f d) -> a -> b -> c -> f e fmap3 f g a b c = f <$> g a b c - thrd :: (a,b,c) -> c - thrd (_,_,x) = x - fst3 :: (a,b,c) -> a fst3 (x,_,_) = x diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index a3a82155ee..3fb2426d33 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -306,7 +306,7 @@ generateBuildInfoOpts sourceMap installedMap mcabalmacros cabalDir distDir local deps = concat [ case M.lookup (fromCabalPackageName name) installedMap of - Just (_, _, Stack.Types.Library _ident ipid) -> ["-package-id=" <> ghcPkgIdString ipid] + Just (_, Stack.Types.Library _ident ipid) -> ["-package-id=" <> ghcPkgIdString ipid] _ -> ["-package=" <> display name <> maybe "" -- This empty case applies to e.g. base. ((("-" <>) . versionString) . sourceVersion) diff --git a/src/Stack/SDist.hs b/src/Stack/SDist.hs index 69438fc8cb..22ed82707f 100644 --- a/src/Stack/SDist.hs +++ b/src/Stack/SDist.hs @@ -126,7 +126,7 @@ getCabalLbs pvpBounds fp = do Just (PSUpstream version _ _) -> Just version Nothing -> case Map.lookup name installedMap of - Just (version, _, _) -> Just version + Just (_, installed) -> Just (installedVersion installed) Nothing -> Nothing diff --git a/src/Stack/Types/Package.hs b/src/Stack/Types/Package.hs index c31d023fbc..316cc562ab 100644 --- a/src/Stack/Types/Package.hs +++ b/src/Stack/Types/Package.hs @@ -332,7 +332,12 @@ dotCabalGetPath dcp = DotCabalFilePath fp -> fp DotCabalCFilePath fp -> fp -type InstalledMap = Map PackageName (Version, InstallLocation, Installed) -- TODO Version is now redundant and can be gleaned from Installed +type InstalledMap = Map PackageName (InstallLocation, Installed) data Installed = Library PackageIdentifier GhcPkgId | Executable PackageIdentifier deriving (Show, Eq, Ord) + +-- | Get the installed Version. +installedVersion :: Installed -> Version +installedVersion (Library (PackageIdentifier _ v) _) = v +installedVersion (Executable (PackageIdentifier _ v)) = v From 42c944b75b034cb85a6884443af716c9ad512d3d Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Fri, 16 Oct 2015 04:16:32 -0700 Subject: [PATCH 042/106] Use short SHA for install paths on windows #1145 --- src/Stack/Constants.hs | 21 +------------- src/Stack/Types/Config.hs | 59 ++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/Stack/Constants.hs b/src/Stack/Constants.hs index 2dfb4b48e0..878329bde7 100644 --- a/src/Stack/Constants.hs +++ b/src/Stack/Constants.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} @@ -52,13 +51,6 @@ import Prelude import Stack.Types.Config import Stack.Types.PackageIdentifier import Stack.Types.PackageName -#ifdef mingw32_HOST_OS -import qualified Crypto.Hash.SHA1 as SHA1 -import qualified Data.ByteString as B -import qualified Data.ByteString.Base16 as Base16 -import qualified Data.ByteString.Char8 as B8 -import qualified Data.Text.Encoding as T -#endif -- | Extensions for anything that can be a Haskell module. haskellModuleExts :: [Text] @@ -217,18 +209,7 @@ distRelativeDir = do parseRelDir $ packageIdentifierString (PackageIdentifier cabalPackageName cabalPkgVer) - -#ifdef mingw32_HOST_OS - -- This is an attempt to shorten path to stack build artifacts dir on Windows to - -- decrease our chances of hitting 260 symbol path limit. - -- The idea is to calculate SHA1 hash from concatenated platform and cabal strings, - -- encode with base 16 and take first 8 symbols of it. - let concatenatedText = T.pack . toFilePath $ platform cabal - sha1 = SHA1.hash $ T.encodeUtf8 concatenatedText - platformAndCabal <- parseRelDir . B8.unpack . B.take 8 $ Base16.encode sha1 -#else - let platformAndCabal = platform cabal -#endif + platformAndCabal <- useShaPathOnWindows (platform cabal) return $ workDirRel $(mkRelDir "dist") diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index c3d16814e1..e923c26da9 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-} @@ -35,7 +36,6 @@ import Data.List (stripPrefix) import Data.Hashable (Hashable) import Data.Map (Map) import qualified Data.Map as Map - import qualified Data.Map.Strict as M import Data.Maybe import Data.Monoid @@ -61,6 +61,10 @@ import Stack.Types.PackageIdentifier import Stack.Types.PackageName import Stack.Types.Version import System.Process.Read (EnvOverride) +#ifdef mingw32_HOST_OS +import qualified Crypto.Hash.SHA1 as SHA1 +import qualified Data.ByteString.Base16 as B16 +#endif -- | The top-level Stackage configuration. data Config = @@ -904,15 +908,6 @@ platformOnlyRelDir = do platform <- asks getPlatform parseRelDir (Distribution.Text.display platform) --- | Relative directory for the platform identifier -platformVariantRelDir - :: (MonadReader env m, HasPlatform env, HasGHCVariant env, MonadThrow m) - => m (Path Rel Dir) -platformVariantRelDir = do - platform <- asks getPlatform - ghcVariant <- asks getGHCVariant - parseRelDir (Distribution.Text.display platform <> ghcVariantSuffix ghcVariant) - -- | Path to .shake files. configShakeFilesDir :: (MonadReader env m, HasBuildConfig env) => m (Path Abs Dir) configShakeFilesDir = liftM ( $(mkRelDir "shake")) configProjectWorkDir @@ -931,20 +926,50 @@ snapshotsDir = do -- | Installation root for dependencies installationRootDeps :: (MonadThrow m, MonadReader env m, HasEnvConfig env) => m (Path Abs Dir) installationRootDeps = do - snapshots <- snapshotsDir - bc <- asks getBuildConfig - name <- parseRelDir $ T.unpack $ resolverName $ bcResolver bc - ghc <- compilerVersionDir - return $ snapshots name ghc + config <- asks getConfig + -- TODO: also useShaPathOnWindows here, once #1173 is resolved. + psc <- platformSnapAndCompilerRel + return $ configStackRoot config $(mkRelDir "snapshots") psc -- | Installation root for locals installationRootLocal :: (MonadThrow m, MonadReader env m, HasEnvConfig env) => m (Path Abs Dir) installationRootLocal = do bc <- asks getBuildConfig + psc <- useShaPathOnWindows =<< platformSnapAndCompilerRel + return $ configProjectWorkDir bc $(mkRelDir "install") psc + +-- | Path for platform followed by snapshot name followed by compiler +-- name. +platformSnapAndCompilerRel + :: (MonadReader env m, HasPlatform env, HasEnvConfig env, MonadThrow m) + => m (Path Rel Dir) +platformSnapAndCompilerRel = do + bc <- asks getBuildConfig + platform <- platformVariantRelDir name <- parseRelDir $ T.unpack $ resolverName $ bcResolver bc ghc <- compilerVersionDir - platform <- platformVariantRelDir - return $ configProjectWorkDir bc $(mkRelDir "install") platform name ghc + useShaPathOnWindows (platform name ghc) + +-- | Relative directory for the platform identifier +platformVariantRelDir + :: (MonadReader env m, HasPlatform env, HasGHCVariant env, MonadThrow m) + => m (Path Rel Dir) +platformVariantRelDir = do + platform <- asks getPlatform + ghcVariant <- asks getGHCVariant + parseRelDir (Distribution.Text.display platform <> ghcVariantSuffix ghcVariant) + +-- | This is an attempt to shorten stack paths on Windows to decrease our +-- chances of hitting 260 symbol path limit. The idea is to calculate +-- SHA1 hash of the path used on other architectures, encode with base +-- 16 and take first 8 symbols of it. +useShaPathOnWindows :: MonadThrow m => Path Rel Dir -> m (Path Rel Dir) +useShaPathOnWindows = +#ifdef mingw32_HOST_OS + parseRelDir . S8.unpack . S8.take 8 . B16.encode . SHA1.hash . encodeUtf8 . T.pack . toFilePath +#else + return +#endif compilerVersionDir :: (MonadThrow m, MonadReader env m, HasEnvConfig env) => m (Path Rel Dir) compilerVersionDir = do From d7afc70c347ad6bbd7429ef549c7f32232c0fd61 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Fri, 16 Oct 2015 04:17:02 -0700 Subject: [PATCH 043/106] Fix GHCJS setup on windows (or so it seems, boot is still running) --- src/Stack/Setup.hs | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index 52e779a451..c4953c2fba 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -850,19 +850,35 @@ installGHCJS version si archiveFile archiveType destDir = do $logDebug $ "Unpacking " <> T.pack (toFilePath archiveFile) runUnpack + let stackYaml = unpackDir $(mkRelFile "stack.yaml") + + -- On windows we need to copy options files out of the install dir. Argh! + -- This is done before the build, so that if it fails, things fail + -- earlier. + stackPath <- liftIO getExecutablePath + mwindowsInstallDir <- case platform of + Platform _ Cabal.Windows -> do + $logSticky "Querying GHCJS install dir" + liftM Just $ getGhcjsInstallDir menv stackPath stackYaml + _ -> return Nothing + $logSticky "Installing GHCJS (this will take a long time) ..." let destBinDir = destDir Path. $(mkRelDir "bin") - stackPath <- liftIO getExecutablePath createTree destBinDir runAndLog (Just unpackDir) stackPath menv [ "--install-ghc" , "--stack-yaml" - , toFilePath (unpackDir $(mkRelFile "stack.yaml")) + , toFilePath stackYaml , "--local-bin-path" , toFilePath destBinDir , "install" - , "-v" ] + forM_ mwindowsInstallDir $ \dir -> do + (_, files) <- listDirectory (dir $(mkRelDir "bin")) + forM_ (filter ((".options" `isSuffixOf`). toFilePath) files) $ \optionsFile -> do + let dest = destDir $(mkRelDir "bin") filename optionsFile + removeFileIfExists dest + copyFile optionsFile dest $logStickyDone "Installed GHCJS." -- Install the downloaded stack binary distribution @@ -925,7 +941,7 @@ bootGhcjs :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) bootGhcjs menv stackYaml = do stackPath <- liftIO getExecutablePath -- Install cabal-install if missing, or if the installed one is old. - mcabal <- getCabalInstallVersion menv stackYaml + mcabal <- getCabalInstallVersion menv stackPath stackYaml shouldInstallCabal <- case mcabal of Nothing -> do $logInfo "No 'cabal' binary found for use with GHCJS. Installing a local copy of 'cabal' from source." @@ -967,9 +983,9 @@ runAndLog mdir name menv args = liftBaseWith $ \restore -> do void $ restore $ sinkProcessStderrStdout mdir menv name args logLines logLines getCabalInstallVersion :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) - => EnvOverride -> Path Abs File -> m (Maybe Version) -getCabalInstallVersion menv stackYaml = do - ebs <- tryProcessStdout Nothing menv "stack" + => EnvOverride -> FilePath -> Path Abs File -> m (Maybe Version) +getCabalInstallVersion menv stackPath stackYaml = do + ebs <- tryProcessStdout Nothing menv stackPath [ "--stack-yaml" , toFilePath stackYaml , "exec" @@ -980,6 +996,17 @@ getCabalInstallVersion menv stackYaml = do Left _ -> return Nothing Right bs -> Just <$> parseVersion (T.encodeUtf8 (T.dropWhileEnd isSpace (T.decodeUtf8 bs))) +getGhcjsInstallDir :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) + => EnvOverride -> FilePath -> Path Abs File -> m (Path Abs Dir) +getGhcjsInstallDir menv stackPath stackYaml = do + bs <- readProcessStdout Nothing menv stackPath + [ "--stack-yaml" + , toFilePath stackYaml + , "path" + , "--local-install-root" + ] + parseAbsDir $ T.unpack $ T.dropWhileEnd isSpace $ T.decodeUtf8 bs + -- | Check if given processes appear to be present, throwing an exception if -- missing. checkDependencies :: (MonadIO m, MonadThrow m, MonadReader env m, HasConfig env) @@ -1087,10 +1114,9 @@ withUnpackedTarball7z name si archiveFile archiveType srcDir destDir = do Just x -> parseAbsFile $ T.unpack x run7z <- setup7z si let tmpName = (FP.dropTrailingPathSeparator $ toFilePath $ dirname destDir) ++ "-tmp" + createTree (parent destDir) withCanonicalizedTempDirectory (toFilePath $ parent destDir) tmpName $ \tmpDir -> do let absSrcDir = tmpDir srcDir - removeTreeIfExists absSrcDir - removeFileIfExists tarFile removeTreeIfExists destDir run7z (parent archiveFile) archiveFile run7z tmpDir tarFile From 67ae101fa6fef0b2d4798f814b3801ed55fef1d4 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Fri, 16 Oct 2015 18:11:48 -0700 Subject: [PATCH 044/106] Have GHCJS setup not invoke new stack processes --- src/Stack/Setup.hs | 114 +++++++++++++++++--------------------- src/Stack/Types/StackT.hs | 20 +++++++ src/Stack/Upgrade.hs | 23 +++----- 3 files changed, 79 insertions(+), 78 deletions(-) diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index c4953c2fba..b2373c3d9f 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -68,12 +68,15 @@ import Path.IO import qualified Paths_stack as Meta import Prelude hiding (concat, elem) -- Fix AMP warning import Safe (readMay) -import Stack.Config (resolvePackageEntry) +import Stack.Build (build) +import Stack.Config (resolvePackageEntry, loadConfig) import Stack.Constants (distRelativeDir, stackProgName) +import Stack.Exec (defaultEnvSettings) import Stack.Fetch import Stack.GhcPkg (createDatabase, getCabalPkgVer, getGlobalDB, mkGhcPackagePath) import Stack.Setup.Installed import Stack.Types +import Stack.Types.Internal (HasTerminal, HasReExec, HasLogLevel) import Stack.Types.StackT import qualified System.Directory as D import System.Environment (getExecutablePath) @@ -178,7 +181,7 @@ instance Show SetupException where , "' option to specify a location"] -- | Modify the environment variables (like PATH) appropriately, possibly doing installation too -setupEnv :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasBuildConfig env, HasHttpManager env, HasGHCVariant env, MonadBaseControl IO m) +setupEnv :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasBuildConfig env, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, HasGHCVariant env, MonadBaseControl IO m) => Maybe Text -- ^ Message to give user when necessary GHC is not available -> m EnvConfig setupEnv mResolveMissingGHC = do @@ -307,7 +310,7 @@ addIncludeLib (ExtraDirs _bins includes libs) config = config } -- | Ensure compiler (ghc or ghcjs) is installed and provide the PATHs to add if necessary -ensureCompiler :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasHttpManager env, HasGHCVariant env, MonadBaseControl IO m) +ensureCompiler :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, HasGHCVariant env, MonadBaseControl IO m) => SetupOpts -> m (Maybe ExtraDirs) ensureCompiler sopts = do @@ -626,7 +629,7 @@ downloadAndInstallTool programsDir si downloadInfo tool installer = do markInstalled tool return tool -downloadAndInstallCompiler :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasGHCVariant env, HasHttpManager env, MonadBaseControl IO m) +downloadAndInstallCompiler :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasGHCVariant env, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, MonadBaseControl IO m) => SetupInfo -> CompilerVersion -> VersionCheck @@ -797,7 +800,7 @@ installGHCPosix version _ archiveFile archiveType destDir = do $logStickyDone $ "Installed GHC." $logDebug $ "GHC installed to " <> T.pack (toFilePath destDir) -installGHCJS :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasHttpManager env, MonadBaseControl IO m) +installGHCJS :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, MonadBaseControl IO m) => Version -> SetupInfo -> Path Abs File @@ -850,29 +853,24 @@ installGHCJS version si archiveFile archiveType destDir = do $logDebug $ "Unpacking " <> T.pack (toFilePath archiveFile) runUnpack + $logSticky "Setting up GHCJS build environment" let stackYaml = unpackDir $(mkRelFile "stack.yaml") + destBinDir = destDir Path. $(mkRelDir "bin") + createTree destBinDir + envConfig <- loadGhcjsEnvConfig stackYaml destBinDir -- On windows we need to copy options files out of the install dir. Argh! -- This is done before the build, so that if it fails, things fail -- earlier. - stackPath <- liftIO getExecutablePath mwindowsInstallDir <- case platform of - Platform _ Cabal.Windows -> do - $logSticky "Querying GHCJS install dir" - liftM Just $ getGhcjsInstallDir menv stackPath stackYaml + Platform _ Cabal.Windows -> + liftM Just $ runInnerStackT envConfig installationRootLocal _ -> return Nothing $logSticky "Installing GHCJS (this will take a long time) ..." - let destBinDir = destDir Path. $(mkRelDir "bin") - createTree destBinDir - runAndLog (Just unpackDir) stackPath menv - [ "--install-ghc" - , "--stack-yaml" - , toFilePath stackYaml - , "--local-bin-path" - , toFilePath destBinDir - , "install" - ] + runInnerStackT envConfig $ + build (\_ -> return ()) Nothing defaultBuildOpts { boptsInstallExes = True } + -- Copy over *.options files needed on windows. forM_ mwindowsInstallDir $ \dir -> do (_, files) <- listDirectory (dir $(mkRelDir "bin")) forM_ (filter ((".options" `isSuffixOf`). toFilePath) files) $ \optionsFile -> do @@ -902,7 +900,7 @@ installDockerStackExe _ archiveFile _ destDir = do ["xf", toFilePath archiveFile, "--strip-components", "1"] Nothing -ensureGhcjsBooted :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasHttpManager env, MonadBaseControl IO m) +ensureGhcjsBooted :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m, HasConfig env, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, MonadReader env m) => EnvOverride -> CompilerVersion -> Bool -> m () ensureGhcjsBooted menv cv shouldBoot = do eres <- try $ sinkProcessStdout Nothing menv "ghcjs" [] (return ()) @@ -933,45 +931,38 @@ ensureGhcjsBooted menv cv shouldBoot = do actualStackYamlExists <- fileExists actualStackYaml when (not actualStackYamlExists) $ fail "Couldn't find GHCJS stack.yaml in old or new location." - bootGhcjs menv actualStackYaml + bootGhcjs actualStackYaml destDir Left err -> throwM err -bootGhcjs :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) - => EnvOverride -> Path Abs File -> m () -bootGhcjs menv stackYaml = do - stackPath <- liftIO getExecutablePath +bootGhcjs :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, MonadReader env m) + => Path Abs File -> Path Abs Dir -> m () +bootGhcjs stackYaml destDir = do + envConfig <- loadGhcjsEnvConfig stackYaml (destDir $(mkRelDir "bin")) + menv <- liftIO $ configEnvOverride (getConfig envConfig) defaultEnvSettings -- Install cabal-install if missing, or if the installed one is old. - mcabal <- getCabalInstallVersion menv stackPath stackYaml + mcabal <- getCabalInstallVersion menv shouldInstallCabal <- case mcabal of Nothing -> do - $logInfo "No 'cabal' binary found for use with GHCJS. Installing a local copy of 'cabal' from source." + $logInfo "No cabal-install binary found for use with GHCJS. Installing a local copy of cabal-install from source." return True Just v | v < $(mkVersion "1.22.4") -> do $logInfo $ - "'cabal' binary found on PATH is too old to be used for booting GHCJS (version " <> + "cabal-install found on PATH is too old to be used for booting GHCJS (version " <> versionText v <> - "). Installing a local copy of 'cabal' from source." + "). Installing a local copy of cabal-install from source." return True | otherwise -> return False when shouldInstallCabal $ do $logSticky "Building cabal-install for use by ghcjs-boot ... " - runAndLog Nothing stackPath menv - [ "--stack-yaml" - , toFilePath stackYaml - , "build" - , "cabal-install" - ] + runInnerStackT envConfig $ + build (\_ -> return ()) + Nothing + defaultBuildOpts { boptsTargets = ["cabal-install"] } $logSticky "Booting GHCJS (this will take a long time) ..." - runAndLog Nothing stackPath menv - [ "--stack-yaml" - , toFilePath stackYaml - , "exec" - , "--no-ghc-package-path" - , "--" - , "ghcjs-boot" - , "--clean" - ] + let envSettings = defaultEnvSettings { esIncludeGhcPackagePath = False } + menv' <- liftIO $ configEnvOverride (getConfig envConfig) envSettings + runAndLog Nothing "ghcjs-boot" menv' ["--clean"] $logStickyDone "GHCJS booted." -- TODO: something similar is done in Stack.Build.Execute. Create some utilities @@ -982,31 +973,26 @@ runAndLog mdir name menv args = liftBaseWith $ \restore -> do let logLines = CB.lines =$ CL.mapM_ (void . restore . monadLoggerLog $(TH.location >>= liftLoc) "" LevelInfo . toLogStr) void $ restore $ sinkProcessStderrStdout mdir menv name args logLines logLines +loadGhcjsEnvConfig :: (MonadIO m, HasHttpManager r, MonadReader r m, HasTerminal r, HasReExec r, HasLogLevel r) + => Path Abs File -> Path b t -> m EnvConfig +loadGhcjsEnvConfig stackYaml binPath = runInnerStackLoggingT $ do + lc <- loadConfig + (mempty + { configMonoidInstallGHC = Just True + , configMonoidLocalBinPath = Just (toFilePath binPath) + }) + (Just stackYaml) + bconfig <- lcLoadBuildConfig lc Nothing + runInnerStackT bconfig $ setupEnv Nothing + getCabalInstallVersion :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) - => EnvOverride -> FilePath -> Path Abs File -> m (Maybe Version) -getCabalInstallVersion menv stackPath stackYaml = do - ebs <- tryProcessStdout Nothing menv stackPath - [ "--stack-yaml" - , toFilePath stackYaml - , "exec" - , "--" - , "cabal" - , "--numeric-version"] + => EnvOverride -> m (Maybe Version) +getCabalInstallVersion menv = do + ebs <- tryProcessStdout Nothing menv "cabal" ["--numeric-version"] case ebs of Left _ -> return Nothing Right bs -> Just <$> parseVersion (T.encodeUtf8 (T.dropWhileEnd isSpace (T.decodeUtf8 bs))) -getGhcjsInstallDir :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) - => EnvOverride -> FilePath -> Path Abs File -> m (Path Abs Dir) -getGhcjsInstallDir menv stackPath stackYaml = do - bs <- readProcessStdout Nothing menv stackPath - [ "--stack-yaml" - , toFilePath stackYaml - , "path" - , "--local-install-root" - ] - parseAbsDir $ T.unpack $ T.dropWhileEnd isSpace $ T.decodeUtf8 bs - -- | Check if given processes appear to be present, throwing an exception if -- missing. checkDependencies :: (MonadIO m, MonadThrow m, MonadReader env m, HasConfig env) diff --git a/src/Stack/Types/StackT.hs b/src/Stack/Types/StackT.hs index f43493a4bc..3051678ae6 100644 --- a/src/Stack/Types/StackT.hs +++ b/src/Stack/Types/StackT.hs @@ -20,6 +20,8 @@ module Stack.Types.StackT ,runStackTGlobal ,runStackLoggingT ,runStackLoggingTGlobal + ,runInnerStackT + ,runInnerStackLoggingT ,newTLSManager ,logSticky ,logStickyDone) @@ -166,6 +168,24 @@ instance HasReExec LoggingEnv where instance HasSupportsUnicode LoggingEnv where getSupportsUnicode = lenvSupportsUnicode +runInnerStackT :: (HasHttpManager r, HasLogLevel r, HasTerminal r, HasReExec r, MonadReader r m, MonadIO m) + => config -> StackT config IO a -> m a +runInnerStackT config inner = do + manager <- asks getHttpManager + logLevel <- asks getLogLevel + terminal <- asks getTerminal + reExec <- asks getReExec + liftIO $ runStackT manager logLevel config terminal reExec inner + +runInnerStackLoggingT :: (HasHttpManager r, HasLogLevel r, HasTerminal r, HasReExec r, MonadReader r m, MonadIO m) + => StackLoggingT IO a -> m a +runInnerStackLoggingT inner = do + manager <- asks getHttpManager + logLevel <- asks getLogLevel + terminal <- asks getTerminal + reExec <- asks getReExec + liftIO $ runStackLoggingT manager logLevel terminal reExec inner + -- | Run the logging monad, using global options. runStackLoggingTGlobal :: MonadIO m => Manager -> GlobalOpts -> StackLoggingT m a -> m a diff --git a/src/Stack/Upgrade.hs b/src/Stack/Upgrade.hs index b9b21ad760..2b1c508943 100644 --- a/src/Stack/Upgrade.hs +++ b/src/Stack/Upgrade.hs @@ -16,7 +16,7 @@ import qualified Data.Monoid import qualified Data.Set as Set import qualified Data.Text as T import Development.GitRev (gitHash) -import Network.HTTP.Client.Conduit (HasHttpManager, getHttpManager) +import Network.HTTP.Client.Conduit (HasHttpManager) import Path import Path.IO import qualified Paths_stack as Paths @@ -80,25 +80,20 @@ upgrade gitRepo mresolver = withCanonicalizedSystemTempDirectory "stack-upgrade" Nothing -> error "Stack.Upgrade.upgrade: invariant violated, unpacked directory not found" Just path -> return $ Just path - manager <- asks getHttpManager - logLevel <- asks getLogLevel - terminal <- asks getTerminal - reExec <- asks getReExec config <- asks getConfig - - forM_ mdir $ \dir -> liftIO $ do - bconfig <- runStackLoggingT manager logLevel terminal reExec $ do + forM_ mdir $ \dir -> do + bconfig <- runInnerStackLoggingT $ do lc <- loadConfig (configConfigMonoid config <> Data.Monoid.mempty { configMonoidInstallGHC = Just True }) (Just $ dir $(mkRelFile "stack.yaml")) lcLoadBuildConfig lc mresolver - envConfig1 <- runStackT manager logLevel bconfig terminal reExec $ setupEnv $ Just $ + envConfig1 <- runInnerStackT bconfig $ setupEnv $ Just $ "Try rerunning with --install-ghc to install the correct GHC into " <> T.pack (toFilePath (configLocalPrograms config)) - runStackT manager logLevel envConfig1 terminal reExec $ - build (const $ return ()) Nothing defaultBuildOpts - { boptsTargets = ["stack"] - , boptsInstallExes = True - } + runInnerStackT envConfig1 $ + build (const $ return ()) Nothing defaultBuildOpts + { boptsTargets = ["stack"] + , boptsInstallExes = True + } From 1bdb6a839fd5045732deeedee8cf2a0018ccf0a7 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Sat, 17 Oct 2015 20:58:03 -0700 Subject: [PATCH 045/106] Configure --with-ghcjs-pkg and --with-ghc-pkg For some reason, this seems to be necessary for GHCJS to configure packages on windows. Also passing "--with-ghc-pkg" since it seems weird to add this only for ghcjs. --- src/Stack/Build/Execute.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 4ae6844c44..a6522cef44 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -601,7 +601,9 @@ ensureConfig newConfigCache pkgDir ExecuteEnv {..} announce cabal cabalfp = do announce menv <- getMinimalEnvOverride let programNames = - if eeCabalPkgVer < $(mkVersion "1.22") then ["ghc"] else ["ghc", "ghcjs"] + if eeCabalPkgVer < $(mkVersion "1.22") + then ["ghc", "ghc-pkg"] + else ["ghc", "ghc-pkg", "ghcjs", "ghcjs-pkg"] exes <- forM programNames $ \name -> do mpath <- findExecutable menv name return $ case mpath of From dfca0eef37361f9682033dca3445671b046e8ad6 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sun, 18 Oct 2015 09:20:11 -0700 Subject: [PATCH 046/106] Adjust stack.cabal to work around Cabal pretty-printer bug for 'stack upload --pvp-bounds' --- doc/MAINTAINER_GUIDE.md | 6 ------ stack.cabal | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/MAINTAINER_GUIDE.md b/doc/MAINTAINER_GUIDE.md index 7212a734e7..7ebf4e5b5a 100644 --- a/doc/MAINTAINER_GUIDE.md +++ b/doc/MAINTAINER_GUIDE.md @@ -62,12 +62,6 @@ for requirements to perform the release, and more details about the tool. * Upload package to Hackage: `stack upload . --pvp-bounds=both` - Note: due to a Cabal pretty-printer bug, this may fail with a syntax error. - This bug is fixed in Cabal HEAD. Can also work around it by running `stack - sdist --pvp-bounds=both`, updating `stack.cabal`'s bounds from the sdist's - version, then uploading with `stack upload .`. Don't forget to undo the change to - `stack.cabal` afterward (don't commit it). - * On a machine with Vagrant installed: * Run `etc/scripts/vagrant-distros.sh` diff --git a/stack.cabal b/stack.cabal index 3d1cb3493e..ed1262ebc0 100644 --- a/stack.cabal +++ b/stack.cabal @@ -283,9 +283,7 @@ test-suite stack-integration-test main-is: IntegrationSpec.hs ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N - if flag(integration-tests) - buildable: True - else + if !flag(integration-tests) buildable: False build-depends: base >= 4.7 && < 10 From 0b2c5d3eba876a1af6721934f96cb70e7bfc247c Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sun, 18 Oct 2015 09:30:34 -0700 Subject: [PATCH 047/106] Fix location of .installed file for Docker-compatible stack exe download --- src/Stack/Setup.hs | 7 ++++--- src/Stack/Setup/Installed.hs | 26 +++++++++++++------------- src/Stack/Solver.hs | 3 ++- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index b2373c3d9f..c44af28002 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -344,7 +344,8 @@ ensureCompiler sopts = do then do getSetupInfo' <- runOnce (getSetupInfo (soptsStackSetupYaml sopts) =<< asks getHttpManager) - installed <- listInstalled + localPrograms <- asks $ configLocalPrograms . getConfig + installed <- listInstalled localPrograms -- Install GHC ghcVariant <- asks getGHCVariant @@ -624,9 +625,9 @@ downloadAndInstallTool :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader en downloadAndInstallTool programsDir si downloadInfo tool installer = do (file, at) <- downloadFromInfo programsDir downloadInfo tool dir <- installDir programsDir tool - unmarkInstalled tool + unmarkInstalled programsDir tool installer si file at dir - markInstalled tool + markInstalled programsDir tool return tool downloadAndInstallCompiler :: (MonadIO m, MonadMask m, MonadLogger m, MonadReader env m, HasConfig env, HasGHCVariant env, HasHttpManager env, HasTerminal env, HasReExec env, HasLogLevel env, MonadBaseControl IO m) diff --git a/src/Stack/Setup/Installed.hs b/src/Stack/Setup/Installed.hs index 29cab9ec56..f0f5395b12 100644 --- a/src/Stack/Setup/Installed.hs +++ b/src/Stack/Setup/Installed.hs @@ -55,27 +55,27 @@ parseToolText (parsePackageIdentifierFromString . T.unpack -> Just pkgId) = Just parseToolText _ = Nothing markInstalled :: (MonadIO m, MonadReader env m, HasConfig env, MonadThrow m) - => Tool + => Path Abs Dir + -> Tool -> m () -markInstalled tool = do - dir <- asks $ configLocalPrograms . getConfig +markInstalled programsPath tool = do fpRel <- parseRelFile $ toolString tool ++ ".installed" - liftIO $ writeFile (toFilePath $ dir fpRel) "installed" + liftIO $ writeFile (toFilePath $ programsPath fpRel) "installed" unmarkInstalled :: (MonadIO m, MonadReader env m, HasConfig env, MonadThrow m) - => Tool + => Path Abs Dir + -> Tool -> m () -unmarkInstalled tool = do - dir <- asks $ configLocalPrograms . getConfig +unmarkInstalled programsPath tool = do fpRel <- parseRelFile $ toolString tool ++ ".installed" - removeFileIfExists $ dir fpRel + removeFileIfExists $ programsPath fpRel listInstalled :: (MonadIO m, MonadReader env m, HasConfig env, MonadThrow m) - => m [Tool] -listInstalled = do - dir <- asks $ configLocalPrograms . getConfig - createTree dir - (_, files) <- listDirectory dir + => Path Abs Dir + -> m [Tool] +listInstalled programsPath = do + createTree programsPath + (_, files) <- listDirectory programsPath return $ mapMaybe toTool files where toTool fp = do diff --git a/src/Stack/Solver.hs b/src/Stack/Solver.hs index b60c8dee7b..4878d805b5 100644 --- a/src/Stack/Solver.hs +++ b/src/Stack/Solver.hs @@ -58,7 +58,8 @@ cabalSolver wc cabalfps constraints userFlags cabalArgs = withSystemTempDirector case mghc of Just _ -> return menv0 Nothing -> do - tools <- listInstalled + localPrograms <- asks $ configLocalPrograms . getConfig + tools <- listInstalled localPrograms let ghcName = $(mkPackageName "ghc") case [version | Tool (PackageIdentifier name version) <- tools, name == ghcName] of [] -> throwM SolverMissingGHC From 525a3647373c6b0a0f770d3cefd98d5411834685 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sat, 17 Oct 2015 22:06:18 +0200 Subject: [PATCH 048/106] Move toFilePathNoTrailingSep to new module Path.Extra --- src/Path/Extra.hs | 9 +++++++++ src/Stack/Docker.hs | 26 +++++++++++++------------- src/Stack/GhcPkg.hs | 13 +++++-------- src/Stack/Image.hs | 4 ++-- src/Stack/Setup.hs | 16 +++++++--------- src/Stack/Setup/Installed.hs | 7 ++----- src/Stack/Types/Build.hs | 20 ++++++++++---------- src/main/Main.hs | 30 +++++++++++++++--------------- stack.cabal | 1 + 9 files changed, 64 insertions(+), 62 deletions(-) create mode 100644 src/Path/Extra.hs diff --git a/src/Path/Extra.hs b/src/Path/Extra.hs new file mode 100644 index 0000000000..289104640a --- /dev/null +++ b/src/Path/Extra.hs @@ -0,0 +1,9 @@ +-- | Extra Path utilities. + +module Path.Extra where + +import Path +import System.FilePath + +toFilePathNoTrailingSep :: Path loc Dir -> FilePath +toFilePathNoTrailingSep = dropTrailingPathSeparator . toFilePath diff --git a/src/Stack/Docker.hs b/src/Stack/Docker.hs index 756efc1f98..1e88ce0597 100644 --- a/src/Stack/Docker.hs +++ b/src/Stack/Docker.hs @@ -49,6 +49,7 @@ import Distribution.System (Platform (Platform), Arch (X86_64), OS (Li import Distribution.Text (display) import Network.HTTP.Client.Conduit (HasHttpManager) import Path +import Path.Extra (toFilePathNoTrailingSep) import Path.IO (getWorkingDir,listDirectory,createTree,removeFile,removeTree,dirExists) import qualified Paths_stack as Meta import Prelude -- Fix redundant import warnings @@ -60,7 +61,7 @@ import Stack.Setup (ensureDockerStackExe) import System.Directory (canonicalizePath, getModificationTime) import System.Environment (lookupEnv,getProgName, getArgs,getExecutablePath) import System.Exit (exitSuccess, exitWith) -import System.FilePath (dropTrailingPathSeparator,takeBaseName) +import System.FilePath (takeBaseName) import System.IO (stderr,stdin,stdout,hIsTerminalDevice) import System.Process.PagerEditor (editByteString) import System.Process.Read @@ -302,16 +303,16 @@ runContainerAndExit getCmdArgs [["create" ,"--net=host" ,"-e",inContainerEnvVar ++ "=1" - ,"-e",stackRootEnvVar ++ "=" ++ toFPNoTrailingSep stackRoot - ,"-e","WORK_WD=" ++ toFPNoTrailingSep pwd - ,"-e","WORK_HOME=" ++ toFPNoTrailingSep sandboxRepoDir - ,"-e","WORK_ROOT=" ++ toFPNoTrailingSep projectRoot - ,"-v",toFPNoTrailingSep stackRoot ++ ":" ++ toFPNoTrailingSep stackRoot - ,"-v",toFPNoTrailingSep projectRoot ++ ":" ++ toFPNoTrailingSep projectRoot - ,"-v",toFPNoTrailingSep sandboxSandboxDir ++ ":" ++ toFPNoTrailingSep sandboxDir - ,"-v",toFPNoTrailingSep sandboxHomeDir ++ ":" ++ toFPNoTrailingSep sandboxRepoDir - ,"-v",toFPNoTrailingSep stackRoot ++ ":" ++ - toFPNoTrailingSep (sandboxRepoDir $(mkRelDir ("." ++ stackProgName ++ "/")))] + ,"-e",stackRootEnvVar ++ "=" ++ toFilePathNoTrailingSep stackRoot + ,"-e","WORK_WD=" ++ toFilePathNoTrailingSep pwd + ,"-e","WORK_HOME=" ++ toFilePathNoTrailingSep sandboxRepoDir + ,"-e","WORK_ROOT=" ++ toFilePathNoTrailingSep projectRoot + ,"-v",toFilePathNoTrailingSep stackRoot ++ ":" ++ toFilePathNoTrailingSep stackRoot + ,"-v",toFilePathNoTrailingSep projectRoot ++ ":" ++ toFilePathNoTrailingSep projectRoot + ,"-v",toFilePathNoTrailingSep sandboxSandboxDir ++ ":" ++ toFilePathNoTrailingSep sandboxDir + ,"-v",toFilePathNoTrailingSep sandboxHomeDir ++ ":" ++ toFilePathNoTrailingSep sandboxRepoDir + ,"-v",toFilePathNoTrailingSep stackRoot ++ ":" ++ + toFilePathNoTrailingSep (sandboxRepoDir $(mkRelDir ("." ++ stackProgName ++ "/")))] ,userEnvVars ,concatMap (\(k,v) -> ["-e", k ++ "=" ++ v]) envVars ,concatMap sandboxSubdirArg sandboxSubdirs @@ -361,8 +362,7 @@ runContainerAndExit getCmdArgs Just ('=':val) -> Just val _ -> Nothing mountArg (Mount host container) = ["-v",host ++ ":" ++ container] - sandboxSubdirArg subdir = ["-v",toFPNoTrailingSep subdir++ ":" ++ toFPNoTrailingSep subdir] - toFPNoTrailingSep = dropTrailingPathSeparator . toFilePath + sandboxSubdirArg subdir = ["-v",toFilePathNoTrailingSep subdir++ ":" ++ toFilePathNoTrailingSep subdir] projectRoot = fromMaybeProjectRoot mprojectRoot -- | Clean-up old docker images and containers. diff --git a/src/Stack/GhcPkg.hs b/src/Stack/GhcPkg.hs index 5aabce49d6..6ad476da65 100644 --- a/src/Stack/GhcPkg.hs +++ b/src/Stack/GhcPkg.hs @@ -43,12 +43,13 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as T import Path (Path, Abs, Dir, toFilePath, parent, parseAbsDir) +import Path.Extra (toFilePathNoTrailingSep) import Path.IO (dirExists, createTree) import Prelude hiding (FilePath) import Stack.Constants import Stack.Types import System.Directory (canonicalizePath, doesDirectoryExist) -import System.FilePath (FilePath, searchPathSeparator, dropTrailingPathSeparator) +import System.FilePath (searchPathSeparator) import System.Process.Read -- | Get the global package database @@ -293,11 +294,7 @@ listGhcPkgDbs menv wc pkgDbs = do mkGhcPackagePath :: Bool -> Path Abs Dir -> Path Abs Dir -> Path Abs Dir -> Text mkGhcPackagePath locals localdb deps globaldb = T.pack $ intercalate [searchPathSeparator] $ concat - [ [toFilePathNoTrailingSlash localdb | locals] - , [toFilePathNoTrailingSlash deps] - , [toFilePathNoTrailingSlash globaldb] + [ [toFilePathNoTrailingSep localdb | locals] + , [toFilePathNoTrailingSep deps] + , [toFilePathNoTrailingSep globaldb] ] - --- TODO: dedupe with copy in Stack.Setup -toFilePathNoTrailingSlash :: Path loc Dir -> FilePath -toFilePathNoTrailingSlash = dropTrailingPathSeparator . toFilePath diff --git a/src/Stack/Image.hs b/src/Stack/Image.hs index 6d024e5b37..60820accf3 100644 --- a/src/Stack/Image.hs +++ b/src/Stack/Image.hs @@ -30,11 +30,11 @@ import qualified Data.Text as T import Data.Typeable import Options.Applicative import Path +import Path.Extra (toFilePathNoTrailingSep) import Path.IO import Stack.Constants import Stack.Types import Stack.Types.Internal -import System.FilePath (dropTrailingPathSeparator) import System.Process type Build e m = (HasBuildConfig e, HasConfig e, HasEnvConfig e, HasTerminal e, MonadBaseControl IO m, MonadCatch m, MonadIO m, MonadLogger m, MonadReader e m) @@ -95,7 +95,7 @@ syncAddContentToDir dir = do -- | Derive an image name from the project directory. imageName :: Path Abs Dir -> String -imageName = map toLower . dropTrailingPathSeparator . toFilePath . dirname +imageName = map toLower . toFilePathNoTrailingSep . dirname -- | Create a general purpose docker image from the temporary -- directory of executables & static content. diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index c44af28002..0574f5c38d 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -64,6 +64,7 @@ import Language.Haskell.TH as TH import Network.HTTP.Client.Conduit import Network.HTTP.Download.Verified import Path +import Path.Extra (toFilePathNoTrailingSep) import Path.IO import qualified Paths_stack as Meta import Prelude hiding (concat, elem) -- Fix AMP warning @@ -269,19 +270,19 @@ setupEnv mResolveMissingGHC = do else id) -- For reasoning and duplication, see: https://github.com/fpco/stack/issues/70 - $ Map.insert "HASKELL_PACKAGE_SANDBOX" (T.pack $ toFilePathNoTrailingSlash deps) + $ Map.insert "HASKELL_PACKAGE_SANDBOX" (T.pack $ toFilePathNoTrailingSep deps) $ Map.insert "HASKELL_PACKAGE_SANDBOXES" (T.pack $ if esIncludeLocals es then intercalate [searchPathSeparator] - [ toFilePathNoTrailingSlash localdb - , toFilePathNoTrailingSlash deps + [ toFilePathNoTrailingSep localdb + , toFilePathNoTrailingSep deps , "" ] else intercalate [searchPathSeparator] - [ toFilePathNoTrailingSlash deps + [ toFilePathNoTrailingSep deps , "" ]) - $ Map.insert "HASKELL_DIST_DIR" (T.pack $ toFilePathNoTrailingSlash distDir) + $ Map.insert "HASKELL_DIST_DIR" (T.pack $ toFilePathNoTrailingSep distDir) $ env !() <- atomicModifyIORef envRef $ \m' -> (Map.insert es eo m', ()) @@ -1100,7 +1101,7 @@ withUnpackedTarball7z name si archiveFile archiveType srcDir destDir = do Nothing -> error $ "Invalid " ++ name ++ " filename: " ++ show archiveFile Just x -> parseAbsFile $ T.unpack x run7z <- setup7z si - let tmpName = (FP.dropTrailingPathSeparator $ toFilePath $ dirname destDir) ++ "-tmp" + let tmpName = (toFilePathNoTrailingSep $ dirname destDir) ++ "-tmp" createTree (parent destDir) withCanonicalizedTempDirectory (toFilePath $ parent destDir) tmpName $ \tmpDir -> do let absSrcDir = tmpDir srcDir @@ -1286,9 +1287,6 @@ sanityCheck menv wc = withCanonicalizedSystemTempDirectory "stack-sanity-check" Left e -> throwM $ GHCSanityCheckCompileFailed e ghc Right _ -> return () -- TODO check that the output of running the command is correct -toFilePathNoTrailingSlash :: Path loc Dir -> FilePath -toFilePathNoTrailingSlash = FP.dropTrailingPathSeparator . toFilePath - -- Remove potentially confusing environment variables removeHaskellEnvVars :: Map Text Text -> Map Text Text removeHaskellEnvVars = diff --git a/src/Stack/Setup/Installed.hs b/src/Stack/Setup/Installed.hs index f0f5395b12..1b1afec8d9 100644 --- a/src/Stack/Setup/Installed.hs +++ b/src/Stack/Setup/Installed.hs @@ -31,10 +31,10 @@ import qualified Data.Text as T import Distribution.System (Platform (..)) import qualified Distribution.System as Cabal import Path +import Path.Extra (toFilePathNoTrailingSep) import Path.IO import Prelude hiding (concat, elem) -- Fix AMP warning import Stack.Types -import qualified System.FilePath as FP import System.Process.Read data Tool @@ -143,7 +143,7 @@ extraDirs tool = do $logWarn $ "binDirs: unexpected OS/tool combo: " <> T.pack (show (x, toolName)) return mempty where - goList = map toFilePathNoTrailingSlash + goList = map toFilePathNoTrailingSep isGHC n = "ghc" == n || "ghc-" `isPrefixOf` n isGHCJS n = "ghcjs" == n @@ -166,6 +166,3 @@ installDir :: (MonadReader env m, HasConfig env, MonadThrow m, MonadLogger m) installDir programsDir tool = do reldir <- parseRelDir $ toolString tool return $ programsDir reldir - -toFilePathNoTrailingSlash :: Path loc Dir -> FilePath -toFilePathNoTrailingSlash = FP.dropTrailingPathSeparator . toFilePath diff --git a/src/Stack/Types/Build.hs b/src/Stack/Types/Build.hs index f5118b655f..94c399ff0a 100644 --- a/src/Stack/Types/Build.hs +++ b/src/Stack/Types/Build.hs @@ -67,6 +67,7 @@ import Distribution.System (Arch) import Distribution.Text (display) import GHC.Generics import Path (Path, Abs, File, Dir, mkRelDir, toFilePath, parseRelDir, ()) +import Path.Extra (toFilePathNoTrailingSep) import Prelude import Stack.Types.FlagName import Stack.Types.GhcPkgId @@ -77,7 +78,7 @@ import Stack.Types.PackageIdentifier import Stack.Types.PackageName import Stack.Types.Version import System.Exit (ExitCode (ExitFailure)) -import System.FilePath (dropTrailingPathSeparator, pathSeparator) +import System.FilePath (pathSeparator) import System.Process.Log (showProcessArgDebug) ---------------------------------------------- @@ -632,17 +633,16 @@ configureOptsDirs bco loc package = concat , map (("--package-db=" ++) . toFilePath) $ case loc of Snap -> bcoExtraDBs bco ++ [bcoSnapDB bco] Local -> bcoExtraDBs bco ++ [bcoSnapDB bco] ++ [bcoLocalDB bco] - , [ "--libdir=" ++ toFilePathNoTrailingSlash (installRoot $(mkRelDir "lib")) - , "--bindir=" ++ toFilePathNoTrailingSlash (installRoot bindirSuffix) - , "--datadir=" ++ toFilePathNoTrailingSlash (installRoot $(mkRelDir "share")) - , "--libexecdir=" ++ toFilePathNoTrailingSlash (installRoot $(mkRelDir "libexec")) - , "--sysconfdir=" ++ toFilePathNoTrailingSlash (installRoot $(mkRelDir "etc")) - , "--docdir=" ++ toFilePathNoTrailingSlash docDir - , "--htmldir=" ++ toFilePathNoTrailingSlash docDir - , "--haddockdir=" ++ toFilePathNoTrailingSlash docDir] + , [ "--libdir=" ++ toFilePathNoTrailingSep (installRoot $(mkRelDir "lib")) + , "--bindir=" ++ toFilePathNoTrailingSep (installRoot bindirSuffix) + , "--datadir=" ++ toFilePathNoTrailingSep (installRoot $(mkRelDir "share")) + , "--libexecdir=" ++ toFilePathNoTrailingSep (installRoot $(mkRelDir "libexec")) + , "--sysconfdir=" ++ toFilePathNoTrailingSep (installRoot $(mkRelDir "etc")) + , "--docdir=" ++ toFilePathNoTrailingSep docDir + , "--htmldir=" ++ toFilePathNoTrailingSep docDir + , "--haddockdir=" ++ toFilePathNoTrailingSep docDir] ] where - toFilePathNoTrailingSlash = dropTrailingPathSeparator . toFilePath installRoot = case loc of Snap -> bcoSnapInstallRoot bco diff --git a/src/main/Main.hs b/src/main/Main.hs index 7fa8f18f41..50422cd74c 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -43,6 +43,7 @@ import Options.Applicative.Builder.Extra import Options.Applicative.Simple import Options.Applicative.Types (readerAsk) import Path +import Path.Extra (toFilePathNoTrailingSep) import Path.IO import qualified Paths_stack as Meta import Prelude hiding (pi, mapM) @@ -76,7 +77,7 @@ import System.Directory (canonicalizePath, doesFileExist, doesDirector import System.Environment (getEnvironment, getProgName) import System.Exit import System.FileLock (lockFile, tryLockFile, unlockFile, SharedExclusive(Exclusive), FileLock) -import System.FilePath (dropTrailingPathSeparator, searchPathSeparator) +import System.FilePath (searchPathSeparator) import System.IO (hIsTerminalDevice, stderr, stdin, stdout, hSetBuffering, BufferMode(..), hPutStrLn, Handle, hGetEncoding, hSetEncoding) import System.Process.Read @@ -403,15 +404,15 @@ paths = [ ( "Global stack root directory" , "global-stack-root" , \pi -> - T.pack (toFilePathNoTrailing (configStackRoot (bcConfig (piBuildConfig pi))))) + T.pack (toFilePathNoTrailingSep (configStackRoot (bcConfig (piBuildConfig pi))))) , ( "Project root (derived from stack.yaml file)" , "project-root" , \pi -> - T.pack (toFilePathNoTrailing (bcRoot (piBuildConfig pi)))) + T.pack (toFilePathNoTrailingSep (bcRoot (piBuildConfig pi)))) , ( "Configuration location (where the stack.yaml file is)" , "config-location" , \pi -> - T.pack (toFilePathNoTrailing (bcStackYaml (piBuildConfig pi)))) + T.pack (toFilePath (bcStackYaml (piBuildConfig pi)))) , ( "PATH environment variable" , "bin-path" , \pi -> @@ -419,11 +420,11 @@ paths = , ( "Installed GHCs (unpacked and archives)" , "ghc-paths" , \pi -> - T.pack (toFilePathNoTrailing (configLocalPrograms (bcConfig (piBuildConfig pi))))) + T.pack (toFilePathNoTrailingSep (configLocalPrograms (bcConfig (piBuildConfig pi))))) , ( "Local bin path where stack installs executables" , "local-bin-path" , \pi -> - T.pack (toFilePathNoTrailing (configLocalBin (bcConfig (piBuildConfig pi))))) + T.pack (toFilePathNoTrailingSep (configLocalBin (bcConfig (piBuildConfig pi))))) , ( "Extra include directories" , "extra-include-dirs" , \pi -> @@ -437,39 +438,38 @@ paths = , ( "Snapshot package database" , "snapshot-pkg-db" , \pi -> - T.pack (toFilePathNoTrailing (piSnapDb pi))) + T.pack (toFilePathNoTrailingSep (piSnapDb pi))) , ( "Local project package database" , "local-pkg-db" , \pi -> - T.pack (toFilePathNoTrailing (piLocalDb pi))) + T.pack (toFilePathNoTrailingSep (piLocalDb pi))) , ( "Global package database" , "global-pkg-db" , \pi -> - T.pack (toFilePathNoTrailing (piGlobalDb pi))) + T.pack (toFilePathNoTrailingSep (piGlobalDb pi))) , ( "GHC_PACKAGE_PATH environment variable" , "ghc-package-path" , \pi -> mkGhcPackagePath True (piLocalDb pi) (piSnapDb pi) (piGlobalDb pi)) , ( "Snapshot installation root" , "snapshot-install-root" , \pi -> - T.pack (toFilePathNoTrailing (piSnapRoot pi))) + T.pack (toFilePathNoTrailingSep (piSnapRoot pi))) , ( "Local project installation root" , "local-install-root" , \pi -> - T.pack (toFilePathNoTrailing (piLocalRoot pi))) + T.pack (toFilePathNoTrailingSep (piLocalRoot pi))) , ( "Snapshot documentation root" , "snapshot-doc-root" , \pi -> - T.pack (toFilePathNoTrailing (piSnapRoot pi docDirSuffix))) + T.pack (toFilePathNoTrailingSep (piSnapRoot pi docDirSuffix))) , ( "Local project documentation root" , "local-doc-root" , \pi -> - T.pack (toFilePathNoTrailing (piLocalRoot pi docDirSuffix))) + T.pack (toFilePathNoTrailingSep (piLocalRoot pi docDirSuffix))) , ( "Dist work directory" , "dist-dir" , \pi -> - T.pack (toFilePathNoTrailing (piDistDir pi)))] - where toFilePathNoTrailing = dropTrailingPathSeparator . toFilePath + T.pack (toFilePathNoTrailingSep (piDistDir pi)))] data SetupCmdOpts = SetupCmdOpts { scoCompilerVersion :: !(Maybe CompilerVersion) diff --git a/stack.cabal b/stack.cabal index ed1262ebc0..5ed01eebff 100644 --- a/stack.cabal +++ b/stack.cabal @@ -106,6 +106,7 @@ library Network.HTTP.Download.Verified Data.Attoparsec.Args Path.IO + Path.Extra other-modules: Network.HTTP.Download Control.Concurrent.Execute Path.Find From 36af26cb4e0a59708c3f20eef082bd4405eb7823 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sun, 18 Oct 2015 19:44:23 +0200 Subject: [PATCH 049/106] Replace stripTrailingSlashT with FP.dropTrailingPathSeparator --- src/System/Process/Read.hs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/System/Process/Read.hs b/src/System/Process/Read.hs index 2c7353e06b..fc9039b134 100644 --- a/src/System/Process/Read.hs +++ b/src/System/Process/Read.hs @@ -53,7 +53,7 @@ import Data.Foldable (forM_) import Data.IORef import Data.Map (Map) import qualified Data.Map as Map -import Data.Maybe (fromMaybe, isJust) +import Data.Maybe (isJust) import Data.Monoid import Data.Text (Text) import qualified Data.Text as T @@ -352,14 +352,9 @@ getEnvOverride platform = augmentPath :: [FilePath] -> Maybe Text -> Text augmentPath dirs mpath = T.intercalate (T.singleton FP.searchPathSeparator) - $ map (stripTrailingSlashT . T.pack) dirs + $ map (T.pack . FP.dropTrailingPathSeparator) dirs ++ maybe [] return mpath -stripTrailingSlashT :: Text -> Text -stripTrailingSlashT t = fromMaybe t $ T.stripSuffix - (T.singleton FP.pathSeparator) - t - -- | Apply 'augmentPath' on the PATH value in the given Map. augmentPathMap :: [FilePath] -> Map Text Text -> Map Text Text augmentPathMap paths origEnv = From c29cb6361bd5e63281a3a55a591b28e5fbf3c993 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sun, 18 Oct 2015 20:15:20 +0200 Subject: [PATCH 050/106] Move functions unrelated to IO from Path.IO to Path.Extra --- src/Path/Extra.hs | 61 +++++++++++++++++++++++++++++++++++++++++--- src/Path/IO.hs | 48 ---------------------------------- src/Stack/Image.hs | 2 +- src/Stack/Package.hs | 1 + 4 files changed, 59 insertions(+), 53 deletions(-) diff --git a/src/Path/Extra.hs b/src/Path/Extra.hs index 289104640a..1f81aca912 100644 --- a/src/Path/Extra.hs +++ b/src/Path/Extra.hs @@ -1,9 +1,62 @@ +{-# LANGUAGE ViewPatterns #-} + -- | Extra Path utilities. -module Path.Extra where +module Path.Extra + (toFilePathNoTrailingSep + ,dropRoot + ,parseCollapsedAbsDir + ,parseCollapsedAbsFile + ) where -import Path -import System.FilePath +import Control.Monad.Catch +import Path +import Path.Internal (Path(..)) +import qualified System.FilePath as FP +-- | Convert to FilePath but don't add a trailing slash. toFilePathNoTrailingSep :: Path loc Dir -> FilePath -toFilePathNoTrailingSep = dropTrailingPathSeparator . toFilePath +toFilePathNoTrailingSep = FP.dropTrailingPathSeparator . toFilePath + +-- | Collapse intermediate "." and ".." directories from path, then parse +-- it with 'parseAbsDir'. +-- (probably should be moved to the Path module) +parseCollapsedAbsDir :: MonadThrow m => FilePath -> m (Path Abs Dir) +parseCollapsedAbsDir = parseAbsDir . collapseFilePath + +-- | Collapse intermediate "." and ".." directories from path, then parse +-- it with 'parseAbsFile'. +-- (probably should be moved to the Path module) +parseCollapsedAbsFile :: MonadThrow m => FilePath -> m (Path Abs File) +parseCollapsedAbsFile = parseAbsFile . collapseFilePath + +-- | Collapse intermediate "." and ".." directories from a path. +-- +-- > collapseFilePath "./foo" == "foo" +-- > collapseFilePath "/bar/../baz" == "/baz" +-- > collapseFilePath "/../baz" == "/../baz" +-- > collapseFilePath "parent/foo/baz/../bar" == "parent/foo/bar" +-- > collapseFilePath "parent/foo/baz/../../bar" == "parent/bar" +-- > collapseFilePath "parent/foo/.." == "parent" +-- > collapseFilePath "/parent/foo/../../bar" == "/bar" +-- +-- (borrowed from @Text.Pandoc.Shared@) +collapseFilePath :: FilePath -> FilePath +collapseFilePath = FP.joinPath . reverse . foldl go [] . FP.splitDirectories + where + go rs "." = rs + go r@(p:rs) ".." = case p of + ".." -> ("..":r) + (checkPathSeperator -> Just True) -> ("..":r) + _ -> rs + go _ (checkPathSeperator -> Just True) = [[FP.pathSeparator]] + go rs x = x:rs + isSingleton [] = Nothing + isSingleton [x] = Just x + isSingleton _ = Nothing + checkPathSeperator = fmap FP.isPathSeparator . isSingleton + +-- | Drop the root (either @\/@ on POSIX or @C:\\@, @D:\\@, etc. on +-- Windows). +dropRoot :: Path Abs t -> Path Rel t +dropRoot (Path l) = Path (FP.dropDrive l) diff --git a/src/Path/IO.hs b/src/Path/IO.hs index dadf9ed561..d9a2e52203 100644 --- a/src/Path/IO.hs +++ b/src/Path/IO.hs @@ -31,9 +31,6 @@ module Path.IO ,copyFileIfExists ,copyDirectoryRecursive ,createTree - ,dropRoot - ,parseCollapsedAbsFile - ,parseCollapsedAbsDir ,withCanonicalizedSystemTempDirectory ,withCanonicalizedTempDirectory) where @@ -46,7 +43,6 @@ import Data.Either import Data.Maybe import Data.Typeable import Path -import Path.Internal (Path(..)) import qualified System.Directory as D import qualified System.FilePath as FP import System.IO.Error @@ -129,44 +125,6 @@ resolveFileMaybe :: (MonadIO m,MonadThrow m) => Path Abs Dir -> FilePath -> m (Maybe (Path Abs File)) resolveFileMaybe = resolveCheckParse D.doesFileExist parseAbsFile --- | Collapse intermediate "." and ".." directories from path, then parse --- it with 'parseAbsFile'. --- (probably should be moved to the Path module) -parseCollapsedAbsFile :: MonadThrow m => FilePath -> m (Path Abs File) -parseCollapsedAbsFile = parseAbsFile . collapseFilePath - --- | Collapse intermediate "." and ".." directories from path, then parse --- it with 'parseAbsDir'. --- (probably should be moved to the Path module) -parseCollapsedAbsDir :: MonadThrow m => FilePath -> m (Path Abs Dir) -parseCollapsedAbsDir = parseAbsDir . collapseFilePath - --- | Collapse intermediate "." and ".." directories from a path. --- --- > collapseFilePath "./foo" == "foo" --- > collapseFilePath "/bar/../baz" == "/baz" --- > collapseFilePath "/../baz" == "/../baz" --- > collapseFilePath "parent/foo/baz/../bar" == "parent/foo/bar" --- > collapseFilePath "parent/foo/baz/../../bar" == "parent/bar" --- > collapseFilePath "parent/foo/.." == "parent" --- > collapseFilePath "/parent/foo/../../bar" == "/bar" --- --- (borrowed from @Text.Pandoc.Shared@) -collapseFilePath :: FilePath -> FilePath -collapseFilePath = FP.joinPath . reverse . foldl go [] . FP.splitDirectories - where - go rs "." = rs - go r@(p:rs) ".." = case p of - ".." -> ("..":r) - (checkPathSeperator -> Just True) -> ("..":r) - _ -> rs - go _ (checkPathSeperator -> Just True) = [[FP.pathSeparator]] - go rs x = x:rs - isSingleton [] = Nothing - isSingleton [x] = Just x - isSingleton _ = Nothing - checkPathSeperator = fmap FP.isPathSeparator . isSingleton - -- | List objects in a directory, excluding "@.@" and "@..@". Entries are not sorted. listDirectory :: (MonadIO m,MonadThrow m) => Path Abs Dir -> m ([Path Abs Dir],[Path Abs File]) listDirectory dir = @@ -282,12 +240,6 @@ copyDirectoryRecursive srcDir destDir = Nothing -> return () Just relSubDir -> copyDirectoryRecursive srcSubDir (destDir relSubDir)) - --- | Drop the root (either @\/@ on POSIX or @C:\\@, @D:\\@, etc. on --- Windows). -dropRoot :: Path Abs t -> Path Rel t -dropRoot (Path l) = Path (FP.dropDrive l) - -- Utility function for a common pattern of ignoring does-not-exist errors. ignoreDoesNotExist :: MonadIO m => IO () -> m () ignoreDoesNotExist f = diff --git a/src/Stack/Image.hs b/src/Stack/Image.hs index 60820accf3..a151f7114a 100644 --- a/src/Stack/Image.hs +++ b/src/Stack/Image.hs @@ -30,7 +30,7 @@ import qualified Data.Text as T import Data.Typeable import Options.Applicative import Path -import Path.Extra (toFilePathNoTrailingSep) +import Path.Extra import Path.IO import Stack.Constants import Stack.Types diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index 3fb2426d33..a4e3f241e4 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -70,6 +70,7 @@ import Distribution.Simple.Utils import Distribution.System (OS (..), Arch, Platform (..)) import Distribution.Text (display, simpleParse) import Path as FL +import Path.Extra import Path.Find import Path.IO import Prelude From 1350417033f34133545765c7e1100a2ef965a753 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Sun, 18 Oct 2015 22:50:07 +0200 Subject: [PATCH 051/106] Replace libVersionFromInstalled with installedVersion --- src/Stack/Dot.hs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Stack/Dot.hs b/src/Stack/Dot.hs index 12f2f7a51c..d4f927f025 100644 --- a/src/Stack/Dot.hs +++ b/src/Stack/Dot.hs @@ -108,11 +108,6 @@ createDependencyGraph dotOpts = do fst3 :: (a,b,c) -> a fst3 (x,_,_) = x --- Given an 'Installed' try to get the 'Version' -libVersionFromInstalled :: Installed -> Maybe Version -libVersionFromInstalled (Library (PackageIdentifier _ v) _) = Just v -libVersionFromInstalled (Executable _) = Nothing - listDependencies :: (HasEnvConfig env ,HasHttpManager env ,HasLogLevel env @@ -195,8 +190,7 @@ createDepLoader sourceMap installed loadPackageDeps pkgName = case Map.lookup pkgName sourceMap of Just (PSLocal lp) -> pure ((packageAllDeps &&& (Just . packageVersion)) (lpPackage lp)) Just (PSUpstream version _ flags) -> loadPackageDeps pkgName version flags - Nothing -> pure (Set.empty, do m' <- T.traverse libVersionFromInstalled installed - Map.lookup pkgName m') + Nothing -> pure (Set.empty, fmap installedVersion (Map.lookup pkgName installed)) -- | Resolve the direct (depth 0) external dependencies of the given local packages localDependencies :: DotOpts -> [LocalPackage] -> [(PackageName,(Set PackageName,Maybe Version))] From ff905886d9df8e13ffe651928ef0d15c686c32d3 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Sun, 18 Oct 2015 23:50:43 -0700 Subject: [PATCH 052/106] Put coverage errors in the html reports --- src/Stack/Build/Coverage.hs | 60 +++++++++++++++++++++++++------------ src/Stack/Build/Execute.hs | 6 ++-- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index d108d83700..bcb5b3a05c 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -97,6 +97,7 @@ generateHpcReport package tests getGhcPkgKey = do generateHpcReportInternal :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) => Path Abs File -> Path Rel Dir -> Text -> [String] -> [String] -> m () generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = do + let reportDest = parent tixSrc subdir -- If a .tix file exists, move it to the HPC output directory -- and generate a report for it. tixFileExists <- fileExists tixSrc @@ -108,7 +109,8 @@ generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = , T.pack (toFilePath tixSrc) , "." ] - else (`onException` $logError ("Error occurred while producing " <> report)) $ do + else (`catch` \err -> generateHpcErrorReport reportDir $ sanitize $ show (err :: ReadProcessException)) $ + (`onException` $logError ("Error occurred while producing " <> report)) $ do -- Directories for .mix files. hpcRelDir <- ( dotHpc) <$> hpcRelativeDir -- Compute arguments used for both "hpc markup" and "hpc report". @@ -120,7 +122,6 @@ generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = -- Look for index files in the correct dir (relative to -- each pkgdir). ["--hpcdir", toFilePath hpcRelDir, "--reset-hpcdirs"] - reportDest = parent tixSrc subdir menv <- getMinimalEnvOverride $logInfo $ "Generating " <> report outputLines <- liftM S8.lines $ readProcessStdout Nothing menv "hpc" @@ -129,15 +130,21 @@ generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = : (args ++ extraReportArgs) ) if all ("(0/0)" `S8.isSuffixOf`) outputLines - then $logError $ T.concat - [ "Error: The " - , report - , " did not consider any code. One possible cause of this is" - , " if your test-suite builds the library code (see stack" - , " issue #1008). It may also indicate a bug in stack or" - , " the hpc program. Please report this issue if you think" - , " your coverage report should have meaningful results." - ] + then do + let msg html = T.concat + [ "Error: The " + , report + , " did not consider any code. One possible cause of this is" + , " if your test-suite builds the library code (see stack " + , if html then "" else "" + , "issue #1008" + , if html then "" else "" + , "). It may also indicate a bug in stack or" + , " the hpc program. Please report this issue if you think" + , " your coverage report should have meaningful results." + ] + $logError (msg False) + generateHpcErrorReport reportDest (msg True) else do -- Print output, stripping @\r@ characters because -- Windows. @@ -145,13 +152,13 @@ generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = $logInfo ("The " <> report <> " is available at " <> T.pack (toFilePath (reportDest $(mkRelFile "hpc_index.html")))) - -- Generate the markup. - void $ readProcessStdout Nothing menv "hpc" - ( "markup" - : toFilePath tixSrc - : ("--destdir=" ++ toFilePath reportDest) - : (args ++ extraMarkupArgs) - ) + -- Generate the markup. + void $ readProcessStdout Nothing menv "hpc" + ( "markup" + : toFilePath tixSrc + : ("--destdir=" ++ toFilePath reportDest) + : (args ++ extraMarkupArgs) + ) generateHpcUnifiedReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) => m () @@ -255,5 +262,20 @@ generateHpcMarkupIndex = do $logInfo $ "\nAn index of the generated HTML coverage reports is available at " <> T.pack (toFilePath outputFile) +generateHpcErrorReport :: MonadIO m => Path Abs Dir -> Text -> m () +generateHpcErrorReport dir err = do + createTree dir + liftIO $ T.writeFile (toFilePath (dir $(mkRelFile "hpc_index.html"))) $ T.concat $ + [ "" + , "

HPC Report Generation Error

" + , "

" + , err + , "

" + , "" + ] + pathToHtml :: Path b t -> Text -pathToHtml = T.dropWhileEnd (=='/') . LT.toStrict . htmlEscape . LT.pack . toFilePath +pathToHtml = T.dropWhileEnd (=='/') . sanitize . toFilePath + +sanitize :: String -> Text +sanitize = LT.toStrict . htmlEscape . LT.pack diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 6c094f0c02..c7fca93dc0 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -482,14 +482,14 @@ executePlan' installedMap plan ee@ExecuteEnv {..} = do if total > 1 then loop 0 else return () + when (toCoverage $ boptsTestOpts eeBuildOpts) $ do + generateHpcUnifiedReport + generateHpcMarkupIndex unless (null errs) $ throwM $ ExecutionFailure errs when (boptsHaddock eeBuildOpts) $ do generateLocalHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeLocals generateDepsHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeLocals generateSnapHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeGlobalDB - when (toCoverage $ boptsTestOpts eeBuildOpts) $ do - generateHpcUnifiedReport - generateHpcMarkupIndex where installedMap' = Map.difference installedMap $ Map.fromList From cfa0c850daae6a04a349be72c5132f852c3bac6d Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 19 Oct 2015 00:06:20 -0700 Subject: [PATCH 053/106] Bring back "Parse package key out of package.conf.inplace #785" This brings back e26dc62fb569d25a9ef9cf14c610d06735bdbd67, but with better error reporting (not fatal, and put in the output HTML), and gracefully handles the case that the cabal file does not have a library stanza (#1162) --- src/Stack/Build/Coverage.hs | 70 ++++++++++++++++++++++++------------- src/Stack/Build/Execute.hs | 8 +---- src/Stack/GhcPkg.hs | 13 ------- 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index bcb5b3a05c..c5e2d4fa7d 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -20,7 +20,7 @@ import Control.Monad.Logger import Control.Monad.Reader (MonadReader, asks) import Control.Monad.Trans.Resource import qualified Data.ByteString.Char8 as S8 -import Data.Foldable (forM_) +import Data.Foldable (forM_, asum) import Data.Function import Data.List import qualified Data.Map.Strict as Map @@ -69,35 +69,48 @@ tixFilePath pkgId tixName = do -- | Generates the HTML coverage report and shows a textual coverage -- summary for a package. generateHpcReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => Package -> [Text] -> (PackageName -> m (Maybe Text)) -> m () -generateHpcReport package tests getGhcPkgKey = do - -- If we're using > GHC 7.10, the hpc 'include' parameter must specify a - -- ghc package key. See + => Path Abs Dir -> Package -> [Text] -> m () +generateHpcReport pkgDir package tests = do + -- If we're using > GHC 7.10, the hpc 'include' parameter must + -- specify a ghc package key. See -- https://github.com/commercialhaskell/stack/issues/785 let pkgName = packageNameText (packageName package) pkgId = packageIdentifierString (packageIdentifier package) compilerVersion <- asks (envConfigCompilerVersion . getEnvConfig) - includeName <- - if getGhcVersion compilerVersion < $(mkVersion "7.10") - then return pkgId - else do - mghcPkgKey <- getGhcPkgKey (packageName package) - case mghcPkgKey of - Nothing -> fail $ "Before computing test coverage report, failed to find GHC package key for " ++ T.unpack pkgName - Just ghcPkgKey -> return $ T.unpack ghcPkgKey + eincludeName <- + -- Pre-7.8 uses plain PKG-version in tix files. + if getGhcVersion compilerVersion < $(mkVersion "7.10") then return $ Right $ Just pkgId + -- We don't expect to find a package key if there is no library. + else if not (packageHasLibrary package) then return $ Right Nothing + -- Look in the + -- See https://github.com/commercialhaskell/stack/issues/1181#issuecomment-148968986 + else do + mghcPkgKey <- findPackageKeyForBuiltPackage pkgDir (packageIdentifier package) + case mghcPkgKey of + Nothing -> do + let msg = "Failed to find GHC package key for " <> pkgName + $logError msg + return $ Left msg + Just ghcPkgKey -> return $ Right $ Just $ T.unpack ghcPkgKey forM_ tests $ \testName -> do tixSrc <- tixFilePath pkgId (T.unpack testName) subdir <- parseRelDir (T.unpack testName) let report = "coverage report for " <> pkgName <> "'s test-suite \"" <> testName <> "\"" - -- Restrict to just the current library code (see #634 - - -- this will likely be customizable in the future) - extraArgs = ["--include", includeName ++ ":"] - generateHpcReportInternal tixSrc subdir report extraArgs extraArgs + reportDir = parent tixSrc subdir + case eincludeName of + Left err -> generateHpcErrorReport reportDir (sanitize (T.unpack err)) + -- Restrict to just the current library code, if there is a + -- library in the package (see #634 - this will likely be + -- customizable in the future) + Right mincludeName -> do + let extraArgs = case mincludeName of + Just includeName -> ["--include", includeName ++ ":"] + Nothing -> [] + generateHpcReportInternal tixSrc reportDir report extraArgs extraArgs generateHpcReportInternal :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => Path Abs File -> Path Rel Dir -> Text -> [String] -> [String] -> m () -generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = do - let reportDest = parent tixSrc subdir + => Path Abs File -> Path Abs Dir -> Text -> [String] -> [String] -> m () +generateHpcReportInternal tixSrc reportDir report extraMarkupArgs extraReportArgs = do -- If a .tix file exists, move it to the HPC output directory -- and generate a report for it. tixFileExists <- fileExists tixSrc @@ -144,19 +157,19 @@ generateHpcReportInternal tixSrc subdir report extraMarkupArgs extraReportArgs = , " your coverage report should have meaningful results." ] $logError (msg False) - generateHpcErrorReport reportDest (msg True) + generateHpcErrorReport reportDir (msg True) else do -- Print output, stripping @\r@ characters because -- Windows. forM_ outputLines ($logInfo . T.decodeUtf8 . S8.filter (not . (=='\r'))) $logInfo ("The " <> report <> " is available at " <> - T.pack (toFilePath (reportDest $(mkRelFile "hpc_index.html")))) + T.pack (toFilePath (reportDir $(mkRelFile "hpc_index.html")))) -- Generate the markup. void $ readProcessStdout Nothing menv "hpc" ( "markup" : toFilePath tixSrc - : ("--destdir=" ++ toFilePath reportDest) + : ("--destdir=" ++ toFilePath reportDir) : (args ++ extraMarkupArgs) ) @@ -185,7 +198,7 @@ generateHpcUnifiedReport = do let tixDest = outputDir $(mkRelFile "unified/unified.tix") createTree (parent tixDest) liftIO $ writeTix (toFilePath tixDest) tix - generateHpcReportInternal tixDest $(mkRelDir "unified") "unified report" [] [] + generateHpcReportInternal tixDest (outputDir $(mkRelDir "unified/unified")) "unified report" [] [] readTixOrLog :: (MonadLogger m, MonadIO m) => Path b File -> m (Maybe Tix) readTixOrLog path = do @@ -279,3 +292,12 @@ pathToHtml = T.dropWhileEnd (=='/') . sanitize . toFilePath sanitize :: String -> Text sanitize = LT.toStrict . htmlEscape . LT.pack + +findPackageKeyForBuiltPackage :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env) + => Path Abs Dir -> PackageIdentifier -> m (Maybe Text) +findPackageKeyForBuiltPackage pkgDir pkgId = do + distDir <- distDirFromDir pkgDir + path <- liftM (distDir ) $ + parseRelFile ("package.conf.inplace/" ++ packageIdentifierString pkgId ++ "-inplace.conf") + contents <- liftIO $ T.readFile (toFilePath path) + return $ asum (map (T.stripPrefix "key: ") (T.lines contents)) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index c7fca93dc0..9dde648a9c 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1194,13 +1194,7 @@ singleTest runInBase topts lptb ac ee task installedMap = do ] return $ Map.singleton testName Nothing - when needHpc $ do - wc <- getWhichCompiler - let pkgDbs = - [ bcoSnapDB (eeBaseConfigOpts ee) - , bcoLocalDB (eeBaseConfigOpts ee) - ] - generateHpcReport package testsToRun (findGhcPkgKey (eeEnvOverride ee) wc pkgDbs) + when needHpc $ generateHpcReport pkgDir package testsToRun bs <- liftIO $ case mlogFile of diff --git a/src/Stack/GhcPkg.hs b/src/Stack/GhcPkg.hs index 5aabce49d6..8f8b2c9147 100644 --- a/src/Stack/GhcPkg.hs +++ b/src/Stack/GhcPkg.hs @@ -11,7 +11,6 @@ module Stack.GhcPkg (findGhcPkgId - ,findGhcPkgKey ,getGlobalDB ,EnvOverride ,envHelper @@ -147,18 +146,6 @@ findGhcPkgId menv wc pkgDbs name = do Just !pid -> return (parseGhcPkgId (T.encodeUtf8 pid)) _ -> return Nothing --- | Get the package key e.g. @foo_9bTCpMF7G4UFWJJvtDrIdB@. --- --- NOTE: GHC > 7.10 only! Will always yield 'Nothing' otherwise. -findGhcPkgKey :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride - -> WhichCompiler - -> [Path Abs Dir] -- ^ package databases - -> PackageName - -> m (Maybe Text) -findGhcPkgKey menv wc pkgDbs name = - findGhcPkgField menv wc pkgDbs (packageNameString name) "key" - -- | Get the version of the package findGhcPkgVersion :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) => EnvOverride From ca727382b1a3d60bb0a0990cc89aa6f37c875f68 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 19 Oct 2015 00:15:36 -0700 Subject: [PATCH 054/106] Replace (flag False True) with (switch) --- src/Stack/Options.hs | 48 ++++++++++++++++++-------------------------- src/main/Main.hs | 4 ++-- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index a9bff6d6e7..fda0555d5d 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -64,10 +64,8 @@ benchOptsParser = BenchmarkOpts metavar "BENCH_ARGS" <> help ("Forward BENCH_ARGS to the benchmark suite. " <> "Supports templates from `cabal bench`"))) - <*> flag False - True - (long "no-run-benchmarks" <> - help "Disable running of benchmarks. (Benchmarks will still be built.)") + <*> switch (long "no-run-benchmarks" <> + help "Disable running of benchmarks. (Benchmarks will still be built.)") addCoverageFlags :: BuildOpts -> BuildOpts addCoverageFlags bopts @@ -115,8 +113,8 @@ buildOptsParser cmd = "copying binaries to the local-bin-path (see 'stack path')" idm - dryRun = flag False True (long "dry-run" <> - help "Don't build anything, just prepare to") + dryRun = switch (long "dry-run" <> + help "Don't build anything, just prepare to") ghcOpts = (\x y z -> concat [x, y, z]) <$> flag [] ["-Wall", "-Werror"] ( long "pedantic" @@ -137,7 +135,7 @@ buildOptsParser cmd = help ("Override flags set in stack.yaml " <> "(applies to local packages and extra-deps)"))) - preFetch = flag False True + preFetch = switch (long "prefetch" <> help "Fetch packages necessary for the build immediately, useful with --dry-run") @@ -167,7 +165,7 @@ buildOptsParser cmd = "continue running after a step fails (default: false for build, true for test/bench)" idm - forceDirty = flag False True + forceDirty = switch (long "force-dirty" <> help "Force treating all local packages as having dirty files (useful for cases where stack can't detect a file change)") @@ -186,15 +184,15 @@ buildOptsParser cmd = metavar "CMD [ARGS]" <> help "Command and arguments to run after a successful build" ) - onlyConfigure = flag False True + onlyConfigure = switch (long "only-configure" <> help "Only perform the configure step, not any builds. Intended for tool usage, may break when used on multiple packages at once!") - reconfigure = flag False True + reconfigure = switch (long "reconfigure" <> help "Perform the configure step even if unnecessary. Useful in some corner cases with custom Setup.hs files") - cabalVerbose = flag False True + cabalVerbose = switch (long "cabal-verbose" <> help "Ask Cabal to be verbose in its output") @@ -463,8 +461,8 @@ ghciOptsParser = GhciOpts (strOption (long "with-ghc" <> metavar "GHC" <> help "Use this command for the GHC to run")) - <*> flag False True (long "no-load" <> - help "Don't load modules on start-up") + <*> switch (long "no-load" <> + help "Don't load modules on start-up") <*> packagesParser <*> optional (textOption @@ -554,14 +552,10 @@ initOptsParser :: Parser InitOpts initOptsParser = InitOpts <$> method <*> overwrite <*> fmap not ignoreSubDirs where - ignoreSubDirs = flag False - True - (long "ignore-subdirs" <> - help "Do not search for .cabal files in sub directories") - overwrite = flag False - True - (long "force" <> - help "Force overwriting of an existing stack.yaml if it exists") + ignoreSubDirs = switch (long "ignore-subdirs" <> + help "Do not search for .cabal files in sub directories") + overwrite = switch (long "force" <> + help "Force overwriting of an existing stack.yaml if it exists") method = solver <|> (MethodResolver <$> resolver) <|> (MethodSnapshot <$> snapPref) @@ -667,14 +661,10 @@ testOptsParser = TestOpts (optional (argsOption(long "test-arguments" <> metavar "TEST_ARGS" <> help "Arguments passed in to the test suite program"))) - <*> flag False - True - (long "coverage" <> - help "Generate a code coverage report") - <*> flag False - True - (long "no-run-tests" <> - help "Disable running of tests. (Tests will still be built.)") + <*> switch (long "coverage" <> + help "Generate a code coverage report") + <*> switch (long "no-run-tests" <> + help "Disable running of tests. (Tests will still be built.)") -- | Parser for @stack new@. newOptsParser :: Parser (NewOpts,InitOpts) diff --git a/src/main/Main.hs b/src/main/Main.hs index 7fa8f18f41..d242e328a8 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -298,8 +298,8 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do addCommand "reset" "Reset the Docker sandbox" dockerResetCmd - (flag False True (long "keep-home" <> - help "Do not delete sandbox's home directory")) + (switch (long "keep-home" <> + help "Do not delete sandbox's home directory")) addCommand Docker.dockerCleanupCmdName "Clean up Docker images and containers" dockerCleanupCmd From a60dac877b094caf4adb76cc4e4e92ad234eaaa4 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 19 Oct 2015 00:57:27 -0700 Subject: [PATCH 055/106] Reflow coverage comments to column 100 --- src/Stack/Build/Coverage.hs | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index c5e2d4fa7d..f9c54bb2fb 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -42,8 +42,8 @@ import Stack.Types import System.Process.Read import Text.Hastache (htmlEscape) --- | Move a tix file into a sub-directory of the hpc report directory. --- Deletes the old one if one is present. +-- | Move a tix file into a sub-directory of the hpc report directory. Deletes the old one if one is +-- present. updateTixFile :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) => Path Abs File -> String -> m () updateTixFile tixSrc pkgId = do @@ -56,8 +56,8 @@ updateTixFile tixSrc pkgId = do createTree (parent tixDest) renameFile tixSrc tixDest --- | Get the tix file location, given the name of the file (without --- extension), and the package identifier string. +-- | Get the tix file location, given the name of the file (without extension), and the package +-- identifier string. tixFilePath :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) => String -> String -> m (Path Abs File) tixFilePath pkgId tixName = do @@ -66,13 +66,11 @@ tixFilePath pkgId tixName = do tixRel <- parseRelFile (tixName ++ ".tix") return (outputDir pkgIdRel tixRel) --- | Generates the HTML coverage report and shows a textual coverage --- summary for a package. +-- | Generates the HTML coverage report and shows a textual coverage summary for a package. generateHpcReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) => Path Abs Dir -> Package -> [Text] -> m () generateHpcReport pkgDir package tests = do - -- If we're using > GHC 7.10, the hpc 'include' parameter must - -- specify a ghc package key. See + -- If we're using > GHC 7.10, the hpc 'include' parameter must specify a ghc package key. See -- https://github.com/commercialhaskell/stack/issues/785 let pkgName = packageNameText (packageName package) pkgId = packageIdentifierString (packageIdentifier package) @@ -82,7 +80,7 @@ generateHpcReport pkgDir package tests = do if getGhcVersion compilerVersion < $(mkVersion "7.10") then return $ Right $ Just pkgId -- We don't expect to find a package key if there is no library. else if not (packageHasLibrary package) then return $ Right Nothing - -- Look in the + -- Look in the inplace DB for the package key. -- See https://github.com/commercialhaskell/stack/issues/1181#issuecomment-148968986 else do mghcPkgKey <- findPackageKeyForBuiltPackage pkgDir (packageIdentifier package) @@ -99,9 +97,8 @@ generateHpcReport pkgDir package tests = do reportDir = parent tixSrc subdir case eincludeName of Left err -> generateHpcErrorReport reportDir (sanitize (T.unpack err)) - -- Restrict to just the current library code, if there is a - -- library in the package (see #634 - this will likely be - -- customizable in the future) + -- Restrict to just the current library code, if there is a library in the package (see + -- #634 - this will likely be customizable in the future) Right mincludeName -> do let extraArgs = case mincludeName of Just includeName -> ["--include", includeName ++ ":"] @@ -111,8 +108,7 @@ generateHpcReport pkgDir package tests = do generateHpcReportInternal :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) => Path Abs File -> Path Abs Dir -> Text -> [String] -> [String] -> m () generateHpcReportInternal tixSrc reportDir report extraMarkupArgs extraReportArgs = do - -- If a .tix file exists, move it to the HPC output directory - -- and generate a report for it. + -- If a .tix file exists, move it to the HPC output directory and generate a report for it. tixFileExists <- fileExists tixSrc if not tixFileExists then $logError $ T.concat @@ -129,11 +125,9 @@ generateHpcReportInternal tixSrc reportDir report extraMarkupArgs extraReportArg -- Compute arguments used for both "hpc markup" and "hpc report". pkgDirs <- Map.keys . envConfigPackages <$> asks getEnvConfig let args = - -- Use index files from all packages (allows cross-package - -- coverage results). + -- Use index files from all packages (allows cross-package coverage results). concatMap (\x -> ["--srcdir", toFilePath x]) pkgDirs ++ - -- Look for index files in the correct dir (relative to - -- each pkgdir). + -- Look for index files in the correct dir (relative to each pkgdir). ["--hpcdir", toFilePath hpcRelDir, "--reset-hpcdirs"] menv <- getMinimalEnvOverride $logInfo $ "Generating " <> report @@ -159,8 +153,7 @@ generateHpcReportInternal tixSrc reportDir report extraMarkupArgs extraReportArg $logError (msg False) generateHpcErrorReport reportDir (msg True) else do - -- Print output, stripping @\r@ characters because - -- Windows. + -- Print output, stripping @\r@ characters because Windows. forM_ outputLines ($logInfo . T.decodeUtf8 . S8.filter (not . (=='\r'))) $logInfo ("The " <> report <> " is available at " <> @@ -207,8 +200,8 @@ readTixOrLog path = do $logError $ "Failed to read tix file " <> T.pack (toFilePath path) return mtix --- | Module names which contain '/' have a package name, and so they --- weren't built into the executable. +-- | Module names which contain '/' have a package name, and so they weren't built into the +-- executable. removeExeModules :: Tix -> Tix removeExeModules (Tix ms) = Tix (filter (\(TixModule name _ _ _) -> '/' `elem` name) ms) From e46481eb83d5e204d2045e28a4d9af6dc79d23aa Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 19 Oct 2015 02:17:01 -0700 Subject: [PATCH 056/106] Filter out unqualified modules from tix files #1191 --- src/Stack/Build/Coverage.hs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index f9c54bb2fb..e4ed536183 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -54,7 +54,14 @@ updateTixFile tixSrc pkgId = do let tixDest = outputDir pkgIdRel filename tixSrc removeFileIfExists tixDest createTree (parent tixDest) - renameFile tixSrc tixDest + -- Remove exe modules because they are problematic. This could be revisited if there's a GHC + -- version that fixes https://ghc.haskell.org/trac/ghc/ticket/1853 + mtix <- readTixOrLog tixSrc + case mtix of + Nothing -> $logError $ "Failed to read " <> T.pack (toFilePath tixSrc) + Just tix -> do + liftIO $ writeTix (toFilePath tixDest) (removeExeModules tix) + removeFileIfExists tixSrc -- | Get the tix file location, given the name of the file (without extension), and the package -- identifier string. From 3b54a9beccb0796c6256a7443d111dd5c4d866ad Mon Sep 17 00:00:00 2001 From: Neil Mitchell Date: Mon, 19 Oct 2015 10:44:50 +0100 Subject: [PATCH 057/106] Simplify the before_test setup Appveyor guarantees `curl` and `7z` on the PATH, so use the default tools, makes it easier to understand for non-Appveyor experts. --- appveyor.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b61e7dbff0..8da9d21878 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,11 +5,8 @@ cache: build: off before_test: -- ps: Invoke-WebRequest "https://github.com/commercialhaskell/stack/releases/download/v0.1.4.0/stack-0.1.4.0-x86_64-windows.zip" -OutFile stack.zip -- ps: Invoke-WebRequest "https://github.com/fpco/minghc/blob/master/bin/7z.exe?raw=true" -OutFile 7z.exe -- ps: Invoke-WebRequest "https://github.com/fpco/minghc/blob/master/bin/7z.dll?raw=true" -OutFile 7z.dll -- 7z x stack.zip -- move stack.exe.exe stack.exe +- curl -ostack.zip -L --insecure http://www.stackage.org/stack/windows-i386 +- 7z x stack.zip stack.exe clone_folder: "c:\\stack" environment: From a05bb8f66703573fb469469334fdc923cee88ebd Mon Sep 17 00:00:00 2001 From: Simeon Filipov Date: Mon, 19 Oct 2015 21:11:41 +0100 Subject: [PATCH 058/106] yaml_configuration.md: Add information about template parameters --- doc/yaml_configuration.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md index 25229fb7c0..ae5c35c5a6 100644 --- a/doc/yaml_configuration.md +++ b/doc/yaml_configuration.md @@ -346,3 +346,33 @@ apply-ghc-options: locals # all local packages, the default ``` Note that `everything` is a slightly dangerous value, as it can break invariants about your snapshot database. + +### templates + +Templates used with `stack new` have a number of parameters that affect the generated code. These can be set for all new projects you create. The result of them can be observed in the generated LICENSE and cabal files. + +The 5 parameters are: `author-email`, `author-name`, `category`, `copyright` and `github-username`. + +* _author-email_ - sets the `maintainer` property in cabal +* _author-name_ - sets the `author` property in cabal and the name used in LICENSE +* _category_ - sets the `category` property in cabal. This is used in Hackage. For examples of categories see [Packages by category](https://hackage.haskell.org/packages/). It makes sense for `category` to be set on a per project basis because it is uncommon for all projects a user creates to belong to the same category. The category can be set per project by passing `-p "category:value"` to the `stack new` command. +* _copyright_ - sets the `copyright` property in cabal. It is typically the name of the holder of the copyright on the package and the year(s) from which copyright is claimed. For example: `Copyright: (c) 2006-2007 Joe Bloggs` +* _github-username_ - used to generate `homepage` and `source-repository` in cabal. For instance `github-username: myusername` and `stack new my-project new-template` would result: +```yaml +homepage: http://github.com/myusername/my-project#readme + +source-repository head + type: git + location: https://github.com/myusername/my-project +``` + +These properties can be set in `config.yaml` as follows: +```yaml +templates: + params: + author-name: Your Name + author-email: youremail@example.com + category: Your Projects Category + copyright: Copyright: (c) 2015 Your Name + github-username: yourusername +``` From 2d13531ff5428687c14c63f84ef98d98dba2dc24 Mon Sep 17 00:00:00 2001 From: mathhun Date: Tue, 20 Oct 2015 09:48:16 +0900 Subject: [PATCH 059/106] Fix comment --- src/Data/Aeson/Extended.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Aeson/Extended.hs b/src/Data/Aeson/Extended.hs index 343fb7f57f..173d3fb0b4 100644 --- a/src/Data/Aeson/Extended.hs +++ b/src/Data/Aeson/Extended.hs @@ -67,7 +67,7 @@ wp ..!= d = do a <- fmap snd p fmap (, a) (fmap fst p .!= d) --- | Tell warning parser about about an expected field, so it doesn't warn about it. +-- | Tell warning parser about an expected field, so it doesn't warn about it. tellJSONField :: Text -> WarningParser () tellJSONField key = tell (mempty { wpmExpectedFields = Set.singleton key}) From fd597d882e09be9595693013ac4b181733f0521b Mon Sep 17 00:00:00 2001 From: Tristan Webb Date: Mon, 28 Sep 2015 23:42:21 -0700 Subject: [PATCH 060/106] Stack config add resolver command config selects the projects stack.yaml, regardless of directory Parsing of config add command Integration test helper (will be used to compare stack.yaml files) Check to see if snapshot exists before writing TODO: Adding differnt fields Additional subcommands for git --- src/Stack/ConfigCmd.hs | 71 +++++++++++++++++++++++++++++++ src/Stack/Options.hs | 30 +++++++++++-- src/main/Main.hs | 17 ++++++++ stack.cabal | 1 + test/integration/lib/StackTest.hs | 14 ++++++ 5 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 src/Stack/ConfigCmd.hs diff --git a/src/Stack/ConfigCmd.hs b/src/Stack/ConfigCmd.hs new file mode 100644 index 0000000000..5f87ff573a --- /dev/null +++ b/src/Stack/ConfigCmd.hs @@ -0,0 +1,71 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- | Make changes to the stack yaml file + +module Stack.ConfigCmd + (ConfigCmdSet(..) + ,cfgCmdSet + ,cfgCmdSetName + ,cfgCmdName) where + +import Control.Monad.Catch (MonadMask, throwM, MonadThrow) +import Control.Monad.IO.Class +import Control.Monad.Logger +import Control.Monad.Reader (MonadReader, asks) +import Control.Monad.Trans.Control (MonadBaseControl) +import qualified Data.ByteString.Builder as B +import qualified Data.ByteString.Lazy as L +import qualified Data.HashMap.Strict as HMap +import qualified Data.Yaml as Yaml +import Network.HTTP.Client.Conduit (HasHttpManager) +import Path +import Stack.BuildPlan +import Stack.Init +import Stack.Types + +data ConfigCmdSet = ConfigCmdSetResolver AbstractResolver + +cfgCmdSet :: ( MonadIO m + , MonadBaseControl IO m + , MonadMask m + , MonadReader env m + , HasConfig env + , HasBuildConfig env + , HasHttpManager env + , HasGHCVariant env + , MonadThrow m + , MonadLogger m) + => ConfigCmdSet -> m () +cfgCmdSet (ConfigCmdSetResolver newResolver) = do + stackYaml <- bcStackYaml <$> asks getBuildConfig + let stackYamlFp = + toFilePath stackYaml + -- We don't need to worry about checking for a valid yaml here + (projectYamlConfig :: Yaml.Object) <- + liftIO (Yaml.decodeFileEither stackYamlFp) >>= + either throwM return + newResolverText <- resolverName <$> makeConcreteResolver newResolver + -- We checking here that the snapshot actually exists + snap <- parseSnapName newResolverText + _ <- loadMiniBuildPlan snap + + let projectYamlConfig' = + HMap.insert + "resolver" + (Yaml.String newResolverText) + projectYamlConfig + liftIO + (L.writeFile + stackYamlFp + (B.toLazyByteString + (B.byteString + (Yaml.encode projectYamlConfig')))) + return () + +cfgCmdName :: String +cfgCmdName = "config" + +cfgCmdSetName :: String +cfgCmdSetName = "set" diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index fda0555d5d..f34bbd6812 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -4,6 +4,7 @@ module Stack.Options (Command(..) ,benchOptsParser ,buildOptsParser + ,configCmdSetParser ,configOptsParser ,dockerOptsParser ,dockerCleanupOptsParser @@ -36,8 +37,9 @@ import Data.Text.Read (decimal) import Options.Applicative.Args import Options.Applicative.Builder.Extra import Options.Applicative.Simple -import Options.Applicative.Types (readerAsk) +import Options.Applicative.Types (fromM, oneM, readerAsk) import Stack.Config (packagesParser) +import Stack.ConfigCmd import Stack.Constants (stackProgName) import Stack.Docker import qualified Stack.Docker as Docker @@ -701,5 +703,27 @@ pvpBoundsOption = readPvpBounds = do s <- readerAsk case parsePvpBounds $ T.pack s of - Left e -> readerError e - Right v -> return v + Left e -> + readerError e + Right v -> + return v + +configCmdSetParser :: Parser ConfigCmdSet +configCmdSetParser = + fromM + (do field <- + oneM + (strArgument + (metavar "FIELD VALUE")) + oneM (fieldToValParser field)) + where + fieldToValParser :: String -> Parser ConfigCmdSet + fieldToValParser s = do + case s of + "resolver" -> + ConfigCmdSetResolver <$> + argument + readAbstractResolver + idm + _ -> + error "parse stack config set field: only set resolver is implemented" diff --git a/src/main/Main.hs b/src/main/Main.hs index d5bfc9225f..075573c37d 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -50,6 +50,7 @@ import Prelude hiding (pi, mapM) import Stack.Build import Stack.Types.Build import Stack.Config +import Stack.ConfigCmd as ConfigCmd import Stack.Constants import qualified Stack.Docker as Docker import Stack.Dot @@ -305,6 +306,13 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do "Clean up Docker images and containers" dockerCleanupCmd dockerCleanupOptsParser) + addSubCommands + ConfigCmd.cfgCmdName + "Subcommands specific to modifying stack.yaml files" + (addCommand ConfigCmd.cfgCmdSetName + "Sets a field in the project's stack.yaml to value" + cfgSetCmd + configCmdSetParser) addSubCommands Image.imgCmdName "Subcommands specific to imaging (EXPERIMENTAL)" @@ -890,6 +898,15 @@ dockerCleanupCmd cleanupOpts go@GlobalOpts{..} = do Docker.preventInContainer $ Docker.cleanup cleanupOpts +cfgSetCmd :: ConfigCmd.ConfigCmdSet -> GlobalOpts -> IO () +cfgSetCmd co go@GlobalOpts{..} = do + withBuildConfigAndLock + go + (\_ -> do env <- ask + runReaderT + (cfgCmdSet co) + env) + imgDockerCmd :: () -> GlobalOpts -> IO () imgDockerCmd () go@GlobalOpts{..} = do withBuildConfigExt diff --git a/stack.cabal b/stack.cabal index 5ed01eebff..6208684976 100644 --- a/stack.cabal +++ b/stack.cabal @@ -52,6 +52,7 @@ library Stack.BuildPlan Stack.Config Stack.Config.Docker + Stack.ConfigCmd Stack.Constants Stack.Docker Stack.Docker.GlobalDB diff --git a/test/integration/lib/StackTest.hs b/test/integration/lib/StackTest.hs index e0170c6e17..1a1e435306 100644 --- a/test/integration/lib/StackTest.hs +++ b/test/integration/lib/StackTest.hs @@ -71,3 +71,17 @@ copy :: FilePath -> FilePath -> IO () copy src dest = do putStrLn ("Copy " ++ show src ++ " to " ++ show dest) System.Directory.copyFile src dest + +fileContentsMatch :: FilePath -> FilePath -> IO () +fileContentsMatch f1 f2 = do + doesExist f1 + doesExist f2 + f1Contents <- readFile f1 + f2Contents <- readFile f2 + if f1Contents == f2Contents + then return () + else error + ("contents do not match for " ++ + show f1 ++ + " " ++ + show f2) From 9e53a802ba950c9a6583e625c5eab08605ac73fb Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Tue, 20 Oct 2015 06:31:08 +0000 Subject: [PATCH 061/106] Use newest Stack for Travis docs Pinging @borsboom @bergmark --- doc/GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/GUIDE.md b/doc/GUIDE.md index 1bdbd114fd..7f7729db19 100644 --- a/doc/GUIDE.md +++ b/doc/GUIDE.md @@ -1603,7 +1603,7 @@ before_install: # Download and unpack the stack executable - mkdir -p ~/.local/bin - export PATH=$HOME/.local/bin:$PATH -- travis_retry curl -L https://github.com/commercialhaskell/stack/releases/download/v0.1.6.0/stack-0.1.6.0-linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' +- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' # This line does all of the work: installs GHC if necessary, build the library, # executables, and test suites, and runs the test suites. --no-terminal works From a380fbd719c39802c64c22d8613731c8a4099db0 Mon Sep 17 00:00:00 2001 From: Luke Iannini Date: Tue, 20 Oct 2015 02:46:30 -0700 Subject: [PATCH 062/106] return () when there's no stty (rather than undefined) to avoid crashes --- src/Stack/Ide.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Ide.hs b/src/Stack/Ide.hs index c85360fc76..7c3f28d37e 100644 --- a/src/Stack/Ide.hs +++ b/src/Stack/Ide.hs @@ -69,7 +69,7 @@ ide targets useropts = do when (os == OSX) (catch (callProcess (Just pwd) menv "stty" ["cbreak", "-imaxbel"]) - (\(_ :: ProcessExitedUnsuccessfully) -> undefined)) + (\(_ :: ProcessExitedUnsuccessfully) -> return ())) callProcess (Just pwd) menv "stack-ide" args where includeDirs pkgopts = From c344e08793a8bb3c575e54c405ecae36fcf5bc98 Mon Sep 17 00:00:00 2001 From: Luke Iannini Date: Tue, 20 Oct 2015 03:01:39 -0700 Subject: [PATCH 063/106] Filter the cabal_macros.h file when checking for dirty files --- src/Stack/Build/Source.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Stack/Build/Source.hs b/src/Stack/Build/Source.hs index beb7ea6a42..5e6a848249 100644 --- a/src/Stack/Build/Source.hs +++ b/src/Stack/Build/Source.hs @@ -338,9 +338,13 @@ loadLocalPackage bopts targets (name, (lpv, gpkg)) = do benchpkg = resolvePackage benchconfig gpkg mbuildCache <- tryGetBuildCache $ lpvRoot lpv (files,_) <- getPackageFilesSimple pkg (lpvCabalFP lpv) + + -- Filter out the cabal_macros file to avoid spurious recompilations + let filteredFiles = Set.filter ((/= $(mkRelFile "cabal_macros.h")) . filename) files + (dirtyFiles, newBuildCache) <- checkBuildCache (fromMaybe Map.empty mbuildCache) - (map toFilePath $ Set.toList files) + (map toFilePath $ Set.toList filteredFiles) return LocalPackage { lpPackage = pkg From c86302276b209866d0814afbab5089d10dfa8f43 Mon Sep 17 00:00:00 2001 From: Tristan Webb Date: Tue, 20 Oct 2015 08:57:10 -0700 Subject: [PATCH 064/106] Fix 7.8.4 compile and remove unnecessary --- src/Stack/ConfigCmd.hs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Stack/ConfigCmd.hs b/src/Stack/ConfigCmd.hs index 5f87ff573a..987845583f 100644 --- a/src/Stack/ConfigCmd.hs +++ b/src/Stack/ConfigCmd.hs @@ -15,8 +15,7 @@ import Control.Monad.IO.Class import Control.Monad.Logger import Control.Monad.Reader (MonadReader, asks) import Control.Monad.Trans.Control (MonadBaseControl) -import qualified Data.ByteString.Builder as B -import qualified Data.ByteString.Lazy as L +import qualified Data.ByteString as S import qualified Data.HashMap.Strict as HMap import qualified Data.Yaml as Yaml import Network.HTTP.Client.Conduit (HasHttpManager) @@ -39,14 +38,14 @@ cfgCmdSet :: ( MonadIO m , MonadLogger m) => ConfigCmdSet -> m () cfgCmdSet (ConfigCmdSetResolver newResolver) = do - stackYaml <- bcStackYaml <$> asks getBuildConfig + stackYaml <- fmap bcStackYaml (asks getBuildConfig) let stackYamlFp = toFilePath stackYaml -- We don't need to worry about checking for a valid yaml here (projectYamlConfig :: Yaml.Object) <- liftIO (Yaml.decodeFileEither stackYamlFp) >>= either throwM return - newResolverText <- resolverName <$> makeConcreteResolver newResolver + newResolverText <- fmap resolverName (makeConcreteResolver newResolver) -- We checking here that the snapshot actually exists snap <- parseSnapName newResolverText _ <- loadMiniBuildPlan snap @@ -57,11 +56,9 @@ cfgCmdSet (ConfigCmdSetResolver newResolver) = do (Yaml.String newResolverText) projectYamlConfig liftIO - (L.writeFile + (S.writeFile stackYamlFp - (B.toLazyByteString - (B.byteString - (Yaml.encode projectYamlConfig')))) + (Yaml.encode projectYamlConfig')) return () cfgCmdName :: String From 4043bb140ca75d6fe7fb5c6c622e0f3706500b91 Mon Sep 17 00:00:00 2001 From: Tristan Webb Date: Tue, 20 Oct 2015 10:39:24 -0700 Subject: [PATCH 065/106] Added changlog about stack config add resolver --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index ecdec0c0cc..141336403a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -9,6 +9,8 @@ Other enhancements: * Added an `allow-newer` config option [#922](https://github.com/commercialhaskell/stack/issues/922) [#770](https://github.com/commercialhaskell/stack/issues/770) * When a Hackage revision invalidates a build plan in a snapshot, trust the snapshot [#770](https://github.com/commercialhaskell/stack/issues/770) +* Added a `stack config set resolver RESOLVER` command. Part of work on [#115](https://github.com/commercialhaskell/stack/issues/115) + Bug fixes: From f71a515ef02aac4ea864bc4a5979c56b884b4ae2 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Tue, 20 Oct 2015 17:22:35 +0000 Subject: [PATCH 066/106] Replace Cabal install with copy and register #1203 --- src/Stack/Build/Execute.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 9dde648a9c..2d788ac516 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1012,8 +1012,9 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in ,sourceFlag]) withMVar eeInstallLock $ \() -> do - announce "install" - cabal False ["install"] + announce "copy/register" + cabal False ["copy"] + cabal False ["register"] let pkgDbs = case taskLocation task of From 7888313565865138f36e6e5488e7e475355a51ad Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Mon, 19 Oct 2015 21:05:29 -0700 Subject: [PATCH 067/106] Add "hpc report" command + use "hpc" dir instead of "hpc/.hpc" in dist dirs + store tix files next to the html files --- src/Path/IO.hs | 6 ++ src/Stack/Build/Coverage.hs | 167 ++++++++++++++++++++++++++++-------- src/Stack/Build/Execute.hs | 6 +- src/Stack/Constants.hs | 5 -- src/Stack/Options.hs | 8 ++ src/main/Main.hs | 14 ++- 6 files changed, 162 insertions(+), 44 deletions(-) diff --git a/src/Path/IO.hs b/src/Path/IO.hs index d9a2e52203..c5cadceb44 100644 --- a/src/Path/IO.hs +++ b/src/Path/IO.hs @@ -64,11 +64,17 @@ getWorkingDir = liftIO (D.canonicalizePath "." >>= parseAbsDir) -- | Parse a directory path. If it's relative, then the absolute version -- is yielded, based off the working directory. +-- +-- NOTE that this only works if the directory exists, but does not +-- ensure that it's a directory. parseRelAsAbsDir :: (MonadThrow m, MonadIO m) => FilePath -> m (Path Abs Dir) parseRelAsAbsDir fp = parseAbsDir =<< liftIO (D.canonicalizePath fp) -- | Parse a file path. If it's relative, then the absolute version is -- yielded, based off the working directory. +-- +-- NOTE that this only works if the file exists, but does not ensure +-- that it's a file. parseRelAsAbsFile :: (MonadThrow m, MonadIO m) => FilePath -> m (Path Abs File) parseRelAsAbsFile fp = parseAbsFile =<< liftIO (D.canonicalizePath fp) diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Build/Coverage.hs index e4ed536183..2973412dcb 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Build/Coverage.hs @@ -3,10 +3,14 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE FlexibleInstances #-} -- | Generate HPC (Haskell Program Coverage) reports module Stack.Build.Coverage - ( updateTixFile + ( deleteHpcReports + , updateTixFile , generateHpcReport + , HpcReportOpts(..) + , generateHpcReportForTargets , generateHpcUnifiedReport , generateHpcMarkupIndex ) where @@ -20,7 +24,7 @@ import Control.Monad.Logger import Control.Monad.Reader (MonadReader, asks) import Control.Monad.Trans.Resource import qualified Data.ByteString.Char8 as S8 -import Data.Foldable (forM_, asum) +import Data.Foldable (forM_, asum, toList) import Data.Function import Data.List import qualified Data.Map.Strict as Map @@ -33,25 +37,35 @@ import qualified Data.Text.IO as T import qualified Data.Text.Lazy as LT import Data.Traversable (forM) import Trace.Hpc.Tix +import Network.HTTP.Client (HasHttpManager) import Path import Path.IO import Prelude hiding (FilePath, writeFile) +import Stack.Build.Source (parseTargetsFromBuildOpts) +import Stack.Build.Target import Stack.Constants import Stack.Package import Stack.Types +import qualified System.Directory as D +import System.FilePath (dropExtension, isPathSeparator) import System.Process.Read import Text.Hastache (htmlEscape) +-- | Invoked at the beginning of running with "--coverage" +deleteHpcReports :: (MonadIO m, MonadThrow m, MonadReader env m, HasEnvConfig env) + => m () +deleteHpcReports = do + hpcDir <- hpcReportDir + removeTreeIfExists hpcDir + -- | Move a tix file into a sub-directory of the hpc report directory. Deletes the old one if one is -- present. updateTixFile :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => Path Abs File -> String -> m () -updateTixFile tixSrc pkgId = do + => PackageName -> Path Abs File -> m () +updateTixFile pkgName tixSrc = do exists <- fileExists tixSrc when exists $ do - outputDir <- hpcReportDir - pkgIdRel <- parseRelDir pkgId - let tixDest = outputDir pkgIdRel filename tixSrc + tixDest <- tixFilePath pkgName (dropExtension (toFilePath (filename tixSrc))) removeFileIfExists tixDest createTree (parent tixDest) -- Remove exe modules because they are problematic. This could be revisited if there's a GHC @@ -63,15 +77,22 @@ updateTixFile tixSrc pkgId = do liftIO $ writeTix (toFilePath tixDest) (removeExeModules tix) removeFileIfExists tixSrc +-- | Get the directory used for hpc reports for the given pkgId. +hpcPkgPath :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) + => PackageName -> m (Path Abs Dir) +hpcPkgPath pkgName = do + outputDir <- hpcReportDir + pkgNameRel <- parseRelDir (packageNameString pkgName) + return (outputDir pkgNameRel) + -- | Get the tix file location, given the name of the file (without extension), and the package -- identifier string. -tixFilePath :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => String -> String -> m (Path Abs File) -tixFilePath pkgId tixName = do - outputDir <- hpcReportDir - pkgIdRel <- parseRelDir pkgId - tixRel <- parseRelFile (tixName ++ ".tix") - return (outputDir pkgIdRel tixRel) +tixFilePath :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) + => PackageName -> String -> m (Path Abs File) +tixFilePath pkgName tixName = do + pkgPath <- hpcPkgPath pkgName + tixRel <- parseRelFile (tixName ++ "/" ++ tixName ++ ".tix") + return (pkgPath tixRel) -- | Generates the HTML coverage report and shows a textual coverage summary for a package. generateHpcReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) @@ -98,10 +119,9 @@ generateHpcReport pkgDir package tests = do return $ Left msg Just ghcPkgKey -> return $ Right $ Just $ T.unpack ghcPkgKey forM_ tests $ \testName -> do - tixSrc <- tixFilePath pkgId (T.unpack testName) - subdir <- parseRelDir (T.unpack testName) + tixSrc <- tixFilePath (packageName package) (T.unpack testName) let report = "coverage report for " <> pkgName <> "'s test-suite \"" <> testName <> "\"" - reportDir = parent tixSrc subdir + reportDir = parent tixSrc case eincludeName of Left err -> generateHpcErrorReport reportDir (sanitize (T.unpack err)) -- Restrict to just the current library code, if there is a library in the package (see @@ -125,10 +145,13 @@ generateHpcReportInternal tixSrc reportDir report extraMarkupArgs extraReportArg , T.pack (toFilePath tixSrc) , "." ] - else (`catch` \err -> generateHpcErrorReport reportDir $ sanitize $ show (err :: ReadProcessException)) $ + else (`catch` \err -> do + let msg = show (err :: ReadProcessException) + $logError (T.pack msg) + generateHpcErrorReport reportDir $ sanitize msg) $ (`onException` $logError ("Error occurred while producing " <> report)) $ do -- Directories for .mix files. - hpcRelDir <- ( dotHpc) <$> hpcRelativeDir + hpcRelDir <- hpcRelativeDir -- Compute arguments used for both "hpc markup" and "hpc report". pkgDirs <- Map.keys . envConfigPackages <$> asks getEnvConfig let args = @@ -173,15 +196,77 @@ generateHpcReportInternal tixSrc reportDir report extraMarkupArgs extraReportArg : (args ++ extraMarkupArgs) ) +data HpcReportOpts = HpcReportOpts + { hroptsInputs :: [Text] + , hroptsAll :: Bool + , hroptsDestDir :: Maybe String + } deriving (Show) + +generateHpcReportForTargets :: (MonadIO m, HasHttpManager env, MonadReader env m, MonadBaseControl IO m, MonadCatch m, MonadLogger m, HasEnvConfig env) + => HpcReportOpts -> m () +generateHpcReportForTargets opts = do + let (tixFiles, targetNames) = partition (".tix" `T.isSuffixOf`) (hroptsInputs opts) + targetTixFiles <- + -- When there aren't any package component arguments, then + -- don't default to all package components. + if not (hroptsAll opts) && null targetNames + then return [] + else do + when (hroptsAll opts && not (null targetNames)) $ + $logWarn $ "Since --all is used, it is redundant to specify these targets: " <> T.pack (show targetNames) + (_,_,targets) <- parseTargetsFromBuildOpts + AllowNoTargets + defaultBuildOpts + { boptsTargets = if hroptsAll opts then [] else targetNames + } + liftM concat $ forM (Map.toList targets) $ \(name, target) -> + case target of + STUnknown -> fail $ + packageNameString name ++ " isn't a known local page" + STNonLocal -> fail $ + "Expected a local package, but " ++ + packageNameString name ++ + " is either an extra-dep or in the snapshot." + STLocalComps comps -> do + pkgPath <- hpcPkgPath name + forM (toList comps) $ \nc -> + case nc of + CTest testName -> + liftM (pkgPath ) $ parseRelFile (T.unpack testName ++ ".tix") + _ -> fail $ + "Can't specify anything except test-suites as hpc report targets (" ++ + packageNameString name ++ + " is used with a non test-suite target)" + STLocalAll -> do + pkgPath <- hpcPkgPath name + exists <- dirExists pkgPath + if exists + then do + (_, files) <- listDirectory pkgPath + return (filter ((".tix" `isSuffixOf`) . toFilePath) files) + else return [] + tixPaths <- liftM (++ targetTixFiles) $ mapM (parseRelAsAbsFile . T.unpack) tixFiles + when (null tixPaths) $ + fail "Not generating combined report, because no targets or tix files are specified." + reportDir <- case hroptsDestDir opts of + Nothing -> liftM ( $(mkRelDir "combined/custom")) hpcReportDir + Just destDir -> do + liftIO $ D.createDirectoryIfMissing True destDir + parseRelAsAbsDir destDir + generateUnionReport "combined report" reportDir tixPaths + generateHpcUnifiedReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) - => m () + => m () generateHpcUnifiedReport = do outputDir <- hpcReportDir createTree outputDir (dirs, _) <- listDirectory outputDir - tixFiles <- liftM concat $ forM dirs $ \dir -> do - (_, files) <- listDirectory dir - return (filter ((".tix" `isSuffixOf`) . toFilePath) files) + tixFiles <- liftM (concat . concat) $ forM (filter (("combined" /=) . dirnameString) dirs) $ \dir -> do + (dirs', _) <- listDirectory dir + forM dirs' $ \dir' -> do + (_, files) <- listDirectory dir' + return (filter ((".tix" `isSuffixOf`) . toFilePath) files) + let reportDir = outputDir $(mkRelDir "combined/all") if length tixFiles < 2 then $logInfo $ T.concat $ [ if null tixFiles then "No tix files" else "Only one tix file" @@ -189,20 +274,27 @@ generateHpcUnifiedReport = do , T.pack (toFilePath outputDir) , ", so not generating a unified coverage report." ] - else do - tixes <- mapM (liftM (fmap removeExeModules) . readTixOrLog) tixFiles - let (errs, tix) = unionTixes (catMaybes tixes) - when (not (null errs)) $ $logWarn $ T.concat $ - "The following modules are left out of the unified report due to version mismatches: " : - intersperse ", " (map T.pack errs) - let tixDest = outputDir $(mkRelFile "unified/unified.tix") - createTree (parent tixDest) - liftIO $ writeTix (toFilePath tixDest) tix - generateHpcReportInternal tixDest (outputDir $(mkRelDir "unified/unified")) "unified report" [] [] + else generateUnionReport "unified report" reportDir tixFiles -readTixOrLog :: (MonadLogger m, MonadIO m) => Path b File -> m (Maybe Tix) +generateUnionReport :: (MonadIO m,MonadReader env m,HasConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,HasEnvConfig env) + => Text -> Path Abs Dir -> [Path Abs File] -> m () +generateUnionReport report reportDir tixFiles = do + tixes <- mapM (liftM (fmap removeExeModules) . readTixOrLog) tixFiles + $logDebug $ "Using the following tix files: " <> T.pack (show tixFiles) + let (errs, tix) = unionTixes (catMaybes tixes) + when (not (null errs)) $ $logWarn $ T.concat $ + "The following modules are left out of the " : report : " due to version mismatches: " : + intersperse ", " (map T.pack errs) + tixDest <- liftM (reportDir ) $ parseRelFile (dirnameString reportDir ++ ".tix") + createTree (parent tixDest) + liftIO $ writeTix (toFilePath tixDest) tix + generateHpcReportInternal tixDest reportDir report [] [] + +readTixOrLog :: (MonadLogger m, MonadIO m, MonadBaseControl IO m) => Path b File -> m (Maybe Tix) readTixOrLog path = do - mtix <- liftIO $ readTix (toFilePath path) + mtix <- liftIO (readTix (toFilePath path)) `catch` \(ErrorCall err) -> do + $logError $ "Error while reading tix: " <> T.pack err + return Nothing when (isNothing mtix) $ $logError $ "Failed to read tix file " <> T.pack (toFilePath path) return mtix @@ -267,7 +359,7 @@ generateHpcMarkupIndex = do else [ "" , "

NOTE: This is merely a listing of the html files found in the coverage reports directory. Some of these reports may be old.

" - , "" + , "" ] ++ rows ++ ["
PackageTestSuite
PackageTestSuiteModification Time
"]) ++ @@ -293,6 +385,9 @@ pathToHtml = T.dropWhileEnd (=='/') . sanitize . toFilePath sanitize :: String -> Text sanitize = LT.toStrict . htmlEscape . LT.pack +dirnameString :: Path r Dir -> String +dirnameString = dropWhileEnd isPathSeparator . toFilePath . dirname + findPackageKeyForBuiltPackage :: (MonadIO m, MonadReader env m, MonadThrow m, HasEnvConfig env) => Path Abs Dir -> PackageIdentifier -> m (Maybe Text) findPackageKeyForBuiltPackage pkgDir pkgId = do diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 2d788ac516..c0f74a75d9 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -420,6 +420,8 @@ executePlan' :: M env m -> ExecuteEnv -> m () executePlan' installedMap plan ee@ExecuteEnv {..} = do + when (toCoverage $ boptsTestOpts eeBuildOpts) deleteHpcReports + wc <- getWhichCompiler cv <- asks $ envConfigCompilerVersion . getEnvConfig case Map.toList $ planUnregisterLocal plan of @@ -1182,7 +1184,7 @@ singleTest runInBase topts lptb ac ee task installedMap = do -- directory into the hpc work dir, for -- tidiness. when needHpc $ - updateTixFile nameTix (packageIdentifierString (packageIdentifier package)) + updateTixFile (packageName package) nameTix return $ case ec of ExitSuccess -> Map.empty _ -> Map.singleton testName $ Just ec @@ -1348,7 +1350,7 @@ extraBuildOptions bopts = do let ddumpOpts = " -ddump-hi -ddump-to-file" case toCoverage (boptsTestOpts bopts) of True -> do - hpcIndexDir <- toFilePath . ( dotHpc) <$> hpcRelativeDir + hpcIndexDir <- toFilePath <$> hpcRelativeDir return ["--ghc-options", "-hpcdir " ++ hpcIndexDir ++ ddumpOpts] False -> return ["--ghc-options", ddumpOpts] diff --git a/src/Stack/Constants.hs b/src/Stack/Constants.hs index 878329bde7..806aa3b803 100644 --- a/src/Stack/Constants.hs +++ b/src/Stack/Constants.hs @@ -30,7 +30,6 @@ module Stack.Constants ,implicitGlobalProjectDir ,hpcRelativeDir ,hpcDirFromDir - ,dotHpc ,objectInterfaceDir ,templatesDir ,defaultUserConfigPathDeprecated @@ -304,10 +303,6 @@ implicitGlobalProjectDir p = p $(mkRelDir "global-project") --- | Where .mix files go. -dotHpc :: Path Rel Dir -dotHpc = $(mkRelDir ".hpc") - -- | Deprecated default global config path. defaultUserConfigPathDeprecated :: Path Abs Dir -> Path Abs File defaultUserConfigPathDeprecated = ( $(mkRelFile "stack.yaml")) diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index f34bbd6812..33092bff53 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -19,6 +19,7 @@ module Stack.Options ,abstractResolverOptsParser ,solverOptsParser ,testOptsParser + ,hpcReportOptsParser ,pvpBoundsOption ) where @@ -692,6 +693,13 @@ newOptsParser = (,) <$> newOpts <*> initOptsParser "Parameter for the template in the format key:value"))) <* abortOption ShowHelpText (long "help" <> help "Show help text.") +-- | Parser for @stack hpc report@. +hpcReportOptsParser :: Parser HpcReportOpts +hpcReportOptsParser = HpcReportOpts + <$> (many $ textArgument $ metavar "TARGET_OR_TIX") + <*> switch (long "all" <> help "Use results from all packages and components") + <*> optional (strOption (long "destdir" <> help "Output directy for HTML report")) + pvpBoundsOption :: Parser PvpBounds pvpBoundsOption = option diff --git a/src/main/Main.hs b/src/main/Main.hs index 075573c37d..a04c5e7e57 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -48,6 +48,7 @@ import Path.IO import qualified Paths_stack as Meta import Prelude hiding (pi, mapM) import Stack.Build +import Stack.Build.Coverage import Stack.Types.Build import Stack.Config import Stack.ConfigCmd as ConfigCmd @@ -319,7 +320,14 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do (addCommand Image.imgDockerCmdName "Build a Docker image for the project" imgDockerCmd - (pure ()))) + (pure ())) + addSubCommands + "hpc" + "Subcommands specific to Haskell Program Coverage" + (do addCommand "report" + "Generate HPC report a combined HPC report" + hpcReportCmd + hpcReportOptsParser)) case eGlobalRun of Left (exitCode :: ExitCode) -> do when isInterpreter $ @@ -979,6 +987,10 @@ listDependenciesCmd sep go = withBuildConfig go (listDependencies sep') queryCmd :: [String] -> GlobalOpts -> IO () queryCmd selectors go = withBuildConfig go $ queryBuildInfo $ map T.pack selectors +-- | Generate a combined HPC report +hpcReportCmd :: HpcReportOpts -> GlobalOpts -> IO () +hpcReportCmd hropts go = withBuildConfig go $ generateHpcReportForTargets hropts + data MainException = InvalidReExecVersion String String deriving (Typeable) instance Exception MainException From da2f02de07bf877134fab9ba6738230783d1aa11 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 18:24:50 -0700 Subject: [PATCH 068/106] Use --coverage flag instead of --ghc-options -fhpc --- src/Stack/Options.hs | 7 ------- src/Stack/Types/Build.hs | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 33092bff53..7592db57f6 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -70,17 +70,10 @@ benchOptsParser = BenchmarkOpts <*> switch (long "no-run-benchmarks" <> help "Disable running of benchmarks. (Benchmarks will still be built.)") -addCoverageFlags :: BuildOpts -> BuildOpts -addCoverageFlags bopts - | toCoverage $ boptsTestOpts bopts - = bopts { boptsGhcOptions = "-fhpc" : boptsGhcOptions bopts } - | otherwise = bopts - -- | Parser for build arguments. buildOptsParser :: Command -> Parser BuildOpts buildOptsParser cmd = - fmap addCoverageFlags $ BuildOpts <$> target <*> libProfiling <*> exeProfiling <*> haddock <*> haddockDeps <*> dryRun <*> ghcOpts <*> flags <*> copyBins <*> preFetch <*> buildSubset <*> diff --git a/src/Stack/Types/Build.hs b/src/Stack/Types/Build.hs index 94c399ff0a..030c4cb31c 100644 --- a/src/Stack/Types/Build.hs +++ b/src/Stack/Types/Build.hs @@ -668,6 +668,7 @@ configureOptsNoDir econfig bco deps wanted isLocal package = concat [ depOptions , ["--enable-library-profiling" | boptsLibProfile bopts || boptsExeProfile bopts] , ["--enable-executable-profiling" | boptsExeProfile bopts] + , ["--coverage" | toCoverage (boptsTestOpts bopts)] , map (\(name,enabled) -> "-f" <> (if enabled From d8ac4c32ea8f3ae155b988ea21c1d4a0a86d8336 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 18:29:35 -0700 Subject: [PATCH 069/106] Move Stack.Build.Coverage to Stack.Coverage --- src/Stack/Build/Execute.hs | 2 +- src/Stack/{Build => }/Coverage.hs | 2 +- src/Stack/Options.hs | 1 + src/main/Main.hs | 10 +++++----- stack.cabal | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) rename src/Stack/{Build => }/Coverage.hs (99%) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index c0f74a75d9..050bd62932 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -63,10 +63,10 @@ import Path import Path.IO import Prelude hiding (FilePath, writeFile) import Stack.Build.Cache -import Stack.Build.Coverage import Stack.Build.Haddock import Stack.Build.Installed import Stack.Build.Source +import Stack.Coverage import Stack.Types.Build import Stack.Fetch as Fetch import Stack.GhcPkg diff --git a/src/Stack/Build/Coverage.hs b/src/Stack/Coverage.hs similarity index 99% rename from src/Stack/Build/Coverage.hs rename to src/Stack/Coverage.hs index 2973412dcb..b71acd7fa6 100644 --- a/src/Stack/Build/Coverage.hs +++ b/src/Stack/Coverage.hs @@ -5,7 +5,7 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances #-} -- | Generate HPC (Haskell Program Coverage) reports -module Stack.Build.Coverage +module Stack.Coverage ( deleteHpcReports , updateTixFile , generateHpcReport diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 7592db57f6..66b72ec159 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -42,6 +42,7 @@ import Options.Applicative.Types (fromM, oneM, readerAsk) import Stack.Config (packagesParser) import Stack.ConfigCmd import Stack.Constants (stackProgName) +import Stack.Coverage (HpcReportOpts(..)) import Stack.Docker import qualified Stack.Docker as Docker import Stack.Dot diff --git a/src/main/Main.hs b/src/main/Main.hs index a04c5e7e57..3b22782023 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -33,9 +33,9 @@ import qualified Data.Text.IO as T import Data.Traversable import Data.Typeable (Typeable) import Data.Version (showVersion) +import Development.GitRev (gitCommitCount) import Distribution.System (buildArch) import Distribution.Text (display) -import Development.GitRev (gitCommitCount) import GHC.IO.Encoding (mkTextEncoding, textEncodingName) import Network.HTTP.Client import Options.Applicative.Args @@ -48,16 +48,17 @@ import Path.IO import qualified Paths_stack as Meta import Prelude hiding (pi, mapM) import Stack.Build -import Stack.Build.Coverage -import Stack.Types.Build import Stack.Config import Stack.ConfigCmd as ConfigCmd import Stack.Constants +import Stack.Coverage import qualified Stack.Docker as Docker import Stack.Dot import Stack.Exec import Stack.Fetch import Stack.FileWatch +import Stack.GhcPkg (getGlobalDB, mkGhcPackagePath) +import Stack.Ghci import Stack.Ide import qualified Stack.Image as Image import Stack.Init @@ -65,12 +66,11 @@ import Stack.New import Stack.Options import Stack.Package (getCabalFileName) import qualified Stack.PackageIndex -import Stack.Ghci -import Stack.GhcPkg (getGlobalDB, mkGhcPackagePath) import Stack.SDist (getSDistTarball) import Stack.Setup import Stack.Solver (solveExtraDeps) import Stack.Types +import Stack.Types.Build import Stack.Types.Internal import Stack.Types.StackT import Stack.Upgrade diff --git a/stack.cabal b/stack.cabal index 6208684976..2de5b7446d 100644 --- a/stack.cabal +++ b/stack.cabal @@ -54,6 +54,7 @@ library Stack.Config.Docker Stack.ConfigCmd Stack.Constants + Stack.Coverage Stack.Docker Stack.Docker.GlobalDB Stack.Dot @@ -92,7 +93,6 @@ library Stack.Types.Package Stack.Build Stack.Build.Cache - Stack.Build.Coverage Stack.Build.ConstructPlan Stack.Build.Execute Stack.Build.Haddock From c12ea70ab5cc89633859949f025054de345029d7 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 18:47:55 -0700 Subject: [PATCH 070/106] Fix a warning --- src/main/Main.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/Main.hs b/src/main/Main.hs index 3b22782023..74900ca879 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -70,7 +70,6 @@ import Stack.SDist (getSDistTarball) import Stack.Setup import Stack.Solver (solveExtraDeps) import Stack.Types -import Stack.Types.Build import Stack.Types.Internal import Stack.Types.StackT import Stack.Upgrade From 1fc28dbb94f64677f595eb38644877dff0a76c87 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 19:01:44 -0700 Subject: [PATCH 071/106] Only mention the coverage index when it has rows --- src/Stack/Coverage.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Stack/Coverage.hs b/src/Stack/Coverage.hs index b71acd7fa6..7d3991260f 100644 --- a/src/Stack/Coverage.hs +++ b/src/Stack/Coverage.hs @@ -364,8 +364,9 @@ generateHpcMarkupIndex = do rows ++ [""]) ++ [""] - $logInfo $ "\nAn index of the generated HTML coverage reports is available at " <> - T.pack (toFilePath outputFile) + when (not (null rows)) $ + $logInfo $ "\nAn index of the generated HTML coverage reports is available at " <> + T.pack (toFilePath outputFile) generateHpcErrorReport :: MonadIO m => Path Abs Dir -> Text -> m () generateHpcErrorReport dir err = do From 7134b7cdbc749b144d403beb6d455bf1ed2efc31 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 19:06:54 -0700 Subject: [PATCH 072/106] Fix build for older versions of http-client --- src/Stack/Coverage.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Coverage.hs b/src/Stack/Coverage.hs index 7d3991260f..15dc03e2d2 100644 --- a/src/Stack/Coverage.hs +++ b/src/Stack/Coverage.hs @@ -37,7 +37,7 @@ import qualified Data.Text.IO as T import qualified Data.Text.Lazy as LT import Data.Traversable (forM) import Trace.Hpc.Tix -import Network.HTTP.Client (HasHttpManager) +import Network.HTTP.Download (HasHttpManager) import Path import Path.IO import Prelude hiding (FilePath, writeFile) From 7e1c1d16ce0ebd02b9c5ee6b6262126ae27c032e Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 19:12:17 -0700 Subject: [PATCH 073/106] Support "stack ghc" command with GHCJS #1054 --- src/Stack/Options.hs | 8 +++----- src/Stack/Types/Config.hs | 16 +++++++++++----- src/main/Main.hs | 33 +++++++++++++++++++++++---------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 66b72ec159..2063b9a142 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -470,8 +470,7 @@ ghciOptsParser = GhciOpts \test suite or benchmark.")) -- | Parser for exec command -execOptsParser :: Maybe String -- ^ command - -> Parser ExecOpts +execOptsParser :: Maybe SpecialExecCmd -> Parser ExecOpts execOptsParser mcmd = ExecOpts <$> pure mcmd @@ -484,16 +483,15 @@ execOptsParser mcmd = meta = (maybe ("CMD ") (const "") mcmd) ++ "-- ARGS (e.g. stack ghc -- X.hs -o x)" -evalOptsParser :: Maybe String -- ^ metavar +evalOptsParser :: String -- ^ metavar -> Parser EvalOpts -evalOptsParser mmeta = +evalOptsParser meta = EvalOpts <$> eoArgsParser <*> execOptsExtraParser where eoArgsParser :: Parser String eoArgsParser = strArgument (metavar meta) - meta = maybe ("CODE") id mmeta -- | Parser for extra options to exec command execOptsExtraParser :: Parser ExecOptsExtra diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index e923c26da9..5047e0491a 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -243,13 +243,18 @@ data EnvSettings = EnvSettings deriving (Show, Eq, Ord) data ExecOpts = ExecOpts - { eoCmd :: !(Maybe String) - -- ^ Usage of @Maybe@ here is nothing more than a hack, to avoid some weird - -- bug in optparse-applicative. See: + { eoCmd :: !(Maybe SpecialExecCmd) + -- ^ When 'Nothing', then the program to run is the head of + -- 'eoArgs'. See: -- https://github.com/commercialhaskell/stack/issues/806 , eoArgs :: ![String] , eoExtra :: !ExecOptsExtra - } + } deriving (Show) + +data SpecialExecCmd + = ExecGhc + | ExecRunGhc + deriving (Show, Eq) data ExecOptsExtra = ExecOptsPlain @@ -257,11 +262,12 @@ data ExecOptsExtra { eoEnvSettings :: !EnvSettings , eoPackages :: ![String] } + deriving (Show) data EvalOpts = EvalOpts { evalArg :: !String , evalExtra :: !ExecOptsExtra - } + } deriving (Show) -- | Parsed global command-line options. data GlobalOpts = GlobalOpts diff --git a/src/main/Main.hs b/src/main/Main.hs index 74900ca879..aa730fa798 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -234,7 +234,7 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do addCommand "ghc" "Run ghc" execCmd - (execOptsParser $ Just "ghc") + (execOptsParser $ Just ExecGhc) addCommand "ghci" "Run ghci in the context of project(s) (experimental)" ghciCmd @@ -242,11 +242,11 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do addCommand "runghc" "Run runghc" execCmd - (execOptsParser $ Just "runghc") + (execOptsParser $ Just ExecRunGhc) addCommand "eval" "Evaluate some haskell code inline. Shortcut for 'stack exec ghc -- -e CODE'" evalCmd - (evalOptsParser $ Just "CODE") -- metavar = "CODE" + (evalOptsParser "CODE") addCommand "clean" "Clean the local packages" cleanCmd @@ -795,14 +795,16 @@ sdistCmd (dirs, mpvpBounds) go = -- | Execute a command. execCmd :: ExecOpts -> GlobalOpts -> IO () -execCmd ExecOpts {..} go@GlobalOpts{..} = do - (cmd, args) <- - case (eoCmd, eoArgs) of - (Just cmd, args) -> return (cmd, args) - (Nothing, cmd:args) -> return (cmd, args) - (Nothing, []) -> error "You must provide a command to exec, e.g. 'stack exec echo Hello World'" +execCmd eo@ExecOpts {..} go@GlobalOpts{..} = do + print eo + let needCmdErr = error "You must provide a command to exec, e.g. 'stack exec echo Hello World'" case eoExtra of ExecOptsPlain -> do + (cmd, args) <- case (eoCmd, eoArgs) of + (Just ExecGhc, args) -> return ("ghc", args) + (Just ExecRunGhc, args) -> return ("runghc", args) + (Nothing, cmd:args) -> return (cmd, args) + (Nothing, []) -> needCmdErr (manager,lc) <- liftIO $ loadConfigWithOpts go withUserFileLock go (configStackRoot $ lcConfig lc) $ \lk -> runStackTGlobal manager (lcConfig lc) go $ @@ -817,6 +819,17 @@ execCmd ExecOpts {..} go@GlobalOpts{..} = do Nothing -- Unlocked already above. ExecOptsEmbellished {..} -> withBuildConfigAndLock go $ \lk -> do + (cmd, args) <- case (eoCmd, eoArgs) of + (Nothing, cmd:args) -> return (cmd, args) + (Nothing, []) -> needCmdErr + (Just scmd, args) -> do + wc <- getWhichCompiler + let cmd = case scmd of + ExecGhc -> compilerExeName wc + -- NOTE: this won't currently work for GHCJS, because it doesn't have + -- a runghcjs binary. It probably will someday, though. + ExecRunGhc -> "run" ++ compilerExeName wc + return (cmd, args) let targets = concatMap words eoPackages unless (null targets) $ Stack.Build.build (const $ return ()) lk defaultBuildOpts @@ -830,7 +843,7 @@ evalCmd :: EvalOpts -> GlobalOpts -> IO () evalCmd EvalOpts {..} go@GlobalOpts {..} = execCmd execOpts go where execOpts = - ExecOpts { eoCmd = Just "ghc" + ExecOpts { eoCmd = Just ExecGhc , eoArgs = ["-e", evalArg] , eoExtra = evalExtra } From ff45507500206aa0165b4f1c3065a5d831185966 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Wed, 21 Oct 2015 06:49:50 +0000 Subject: [PATCH 074/106] --build/--no-build flags to stack image container --- src/main/Main.hs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/Main.hs b/src/main/Main.hs index aa730fa798..e67fdd2d3e 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -319,7 +319,10 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do (addCommand Image.imgDockerCmdName "Build a Docker image for the project" imgDockerCmd - (pure ())) + (boolFlags True + "build" + "building the project before creating the container" + idm)) addSubCommands "hpc" "Subcommands specific to Haskell Program Coverage" @@ -927,13 +930,13 @@ cfgSetCmd co go@GlobalOpts{..} = do (cfgCmdSet co) env) -imgDockerCmd :: () -> GlobalOpts -> IO () -imgDockerCmd () go@GlobalOpts{..} = do +imgDockerCmd :: Bool -> GlobalOpts -> IO () +imgDockerCmd rebuild go@GlobalOpts{..} = do withBuildConfigExt go Nothing (\lk -> - do Stack.Build.build + do when rebuild $ Stack.Build.build (const (return ())) lk defaultBuildOpts From 4701095a197e009a3590505642d69e051cdb9d50 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 19:42:35 -0700 Subject: [PATCH 075/106] A couple ChangeLog updates --- ChangeLog.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 141336403a..0b2c82c7f3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,7 +10,8 @@ Other enhancements: * Added an `allow-newer` config option [#922](https://github.com/commercialhaskell/stack/issues/922) [#770](https://github.com/commercialhaskell/stack/issues/770) * When a Hackage revision invalidates a build plan in a snapshot, trust the snapshot [#770](https://github.com/commercialhaskell/stack/issues/770) * Added a `stack config set resolver RESOLVER` command. Part of work on [#115](https://github.com/commercialhaskell/stack/issues/115) - +* `stack setup` can now install GHCJS on windows. See [#1145](https://github.com/commercialhaskell/stack/issues/1145) and [#749](https://github.com/commercialhaskell/stack/issues/749) +* `stack hpc report` command added, which generates reports for HPC tix files Bug fixes: @@ -18,7 +19,7 @@ Bug fixes: Major changes: -* "stack setup" now supports building and booting GHCJS from source tarball. +* `stack setup` now supports building and booting GHCJS from source tarball. * On Windows, build directories no longer display "pretty" information (like x86_64-windows/Cabal-1.22.4.0), but rather a hash of that content. The reason is to avoid the 260 character path limitation on From 2d3bc64a1c3010a22c0c3e1a34151f6c652496ef Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 20:47:24 -0700 Subject: [PATCH 076/106] Add field and flag for specifying compiler #1190 --- src/Stack/Config.hs | 27 +++++++++++++++++---------- src/Stack/Init.hs | 1 + src/Stack/Options.hs | 16 +++++++++++++++- src/Stack/Setup.hs | 2 +- src/Stack/Types/Config.hs | 10 ++++++++-- src/Stack/Upgrade.hs | 2 +- src/main/Main.hs | 4 ++-- src/test/Stack/BuildPlanSpec.hs | 2 +- src/test/Stack/ConfigSpec.hs | 6 +++--- 9 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs index f646efd5bf..28de0964c5 100644 --- a/src/Stack/Config.hs +++ b/src/Stack/Config.hs @@ -295,8 +295,9 @@ loadBuildConfig :: (MonadLogger m, MonadIO m, MonadCatch m, MonadReader env m, H => Maybe (Project, Path Abs File, ConfigMonoid) -> Config -> Maybe AbstractResolver -- override resolver + -> Maybe CompilerVersion -- override compiler -> m BuildConfig -loadBuildConfig mproject config mresolver = do +loadBuildConfig mproject config mresolver mcompiler = do env <- ask miniConfig <- loadMiniConfig config @@ -340,6 +341,7 @@ loadBuildConfig mproject config mresolver = do , projectExtraDeps = mempty , projectFlags = mempty , projectResolver = r + , projectCompiler = Nothing , projectExtraPackageDBs = [] } liftIO $ do @@ -362,17 +364,22 @@ loadBuildConfig mproject config mresolver = do Nothing -> return $ projectResolver project' Just aresolver -> do runReaderT (makeConcreteResolver aresolver) miniConfig - let project = project' { projectResolver = resolver } + let project = project' + { projectResolver = resolver + , projectCompiler = mcompiler <|> projectCompiler project' + } wantedCompiler <- - case projectResolver project of - ResolverSnapshot snapName -> do - mbp <- runReaderT (loadMiniBuildPlan snapName) miniConfig - return $ mbpCompilerVersion mbp - ResolverCustom _name url -> do - mbp <- runReaderT (parseCustomMiniBuildPlan stackYamlFP url) miniConfig - return $ mbpCompilerVersion mbp - ResolverCompiler wantedCompiler -> return wantedCompiler + case projectCompiler project of + Just wantedCompiler -> return wantedCompiler + Nothing -> case projectResolver project of + ResolverSnapshot snapName -> do + mbp <- runReaderT (loadMiniBuildPlan snapName) miniConfig + return $ mbpCompilerVersion mbp + ResolverCustom _name url -> do + mbp <- runReaderT (parseCustomMiniBuildPlan stackYamlFP url) miniConfig + return $ mbpCompilerVersion mbp + ResolverCompiler wantedCompiler -> return wantedCompiler extraPackageDBs <- mapM parseRelAsAbsDir (projectExtraPackageDBs project) diff --git a/src/Stack/Init.hs b/src/Stack/Init.hs index 44baf6355b..83af318ea6 100644 --- a/src/Stack/Init.hs +++ b/src/Stack/Init.hs @@ -94,6 +94,7 @@ initProject currDir initOpts = do , projectExtraDeps = extraDeps , projectFlags = flags , projectResolver = r + , projectCompiler = Nothing , projectExtraPackageDBs = [] } pkgs = map toPkg cabalfps diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 2063b9a142..4b8cbbfc6f 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -16,7 +16,6 @@ module Stack.Options ,newOptsParser ,logLevelOptsParser ,ghciOptsParser - ,abstractResolverOptsParser ,solverOptsParser ,testOptsParser ,hpcReportOptsParser @@ -532,6 +531,7 @@ globalOptsParser defaultTerminal = logLevelOptsParser <*> configOptsParser False <*> optional abstractResolverOptsParser <*> + optional compilerOptsParser <*> flag defaultTerminal False @@ -623,6 +623,20 @@ readAbstractResolver = do Left e -> readerError $ show e Right x -> return $ ARResolver x +compilerOptsParser :: Parser CompilerVersion +compilerOptsParser = + option readCompilerVersion + (long "compiler" <> + metavar "COMPILER" <> + help "Use the specified compiler") + +readCompilerVersion :: ReadM CompilerVersion +readCompilerVersion = do + s <- readerAsk + case parseCompilerVersion (T.pack s) of + Nothing -> readerError $ "Failed to parse compiler: " ++ s + Just x -> return x + -- | GHC variant parser ghcVariantParser :: Parser GHCVariant ghcVariantParser = diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs index 0574f5c38d..e14fb7f5f8 100644 --- a/src/Stack/Setup.hs +++ b/src/Stack/Setup.hs @@ -984,7 +984,7 @@ loadGhcjsEnvConfig stackYaml binPath = runInnerStackLoggingT $ do , configMonoidLocalBinPath = Just (toFilePath binPath) }) (Just stackYaml) - bconfig <- lcLoadBuildConfig lc Nothing + bconfig <- lcLoadBuildConfig lc Nothing Nothing runInnerStackT bconfig $ setupEnv Nothing getCabalInstallVersion :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadCatch m) diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index 5047e0491a..c53c34d2c3 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -275,6 +275,7 @@ data GlobalOpts = GlobalOpts , globalLogLevel :: !LogLevel -- ^ Log level , globalConfigMonoid :: !ConfigMonoid -- ^ Config monoid, for passing into 'loadConfig' , globalResolver :: !(Maybe AbstractResolver) -- ^ Resolver override + , globalCompiler :: !(Maybe CompilerVersion) -- ^ Compiler override , globalTerminal :: !Bool -- ^ We're in a terminal? , globalStackYaml :: !(Maybe FilePath) -- ^ Override project stack.yaml } deriving (Show) @@ -356,7 +357,7 @@ instance HasEnvConfig EnvConfig where data LoadConfig m = LoadConfig { lcConfig :: !Config -- ^ Top-level Stack configuration. - , lcLoadBuildConfig :: !(Maybe AbstractResolver -> m BuildConfig) + , lcLoadBuildConfig :: !(Maybe AbstractResolver -> Maybe CompilerVersion -> m BuildConfig) -- ^ Action to load the remaining 'BuildConfig'. , lcProjectRoot :: !(Maybe (Path Abs Dir)) -- ^ The project root directory, if in a project. @@ -448,12 +449,15 @@ data Project = Project -- ^ Per-package flag overrides , projectResolver :: !Resolver -- ^ How we resolve which dependencies to use + , projectCompiler :: !(Maybe CompilerVersion) + -- ^ When specified, overrides which compiler to use , projectExtraPackageDBs :: ![FilePath] } deriving Show instance ToJSON Project where - toJSON p = object + toJSON p = object $ + (maybe id (\cv -> (("compiler" .= cv) :)) (projectCompiler p)) [ "packages" .= projectPackages p , "extra-deps" .= map fromTuple (Map.toList $ projectExtraDeps p) , "flags" .= projectFlags p @@ -1079,6 +1083,7 @@ instance (warnings ~ [JSONWarning]) => FromJSON (ProjectAndConfigMonoid, warning flags <- o ..:? "flags" ..!= mempty resolver <- jsonSubWarnings (o ..: "resolver") + compiler <- o ..:? "compiler" config <- parseConfigMonoidJSON o extraPackageDBs <- o ..:? "extra-package-dbs" ..!= [] let project = Project @@ -1086,6 +1091,7 @@ instance (warnings ~ [JSONWarning]) => FromJSON (ProjectAndConfigMonoid, warning , projectExtraDeps = extraDeps , projectFlags = flags , projectResolver = resolver + , projectCompiler = compiler , projectExtraPackageDBs = extraPackageDBs } return $ ProjectAndConfigMonoid project config diff --git a/src/Stack/Upgrade.hs b/src/Stack/Upgrade.hs index 2b1c508943..03eb9dd147 100644 --- a/src/Stack/Upgrade.hs +++ b/src/Stack/Upgrade.hs @@ -88,7 +88,7 @@ upgrade gitRepo mresolver = withCanonicalizedSystemTempDirectory "stack-upgrade" { configMonoidInstallGHC = Just True }) (Just $ dir $(mkRelFile "stack.yaml")) - lcLoadBuildConfig lc mresolver + lcLoadBuildConfig lc mresolver Nothing envConfig1 <- runInnerStackT bconfig $ setupEnv $ Just $ "Try rerunning with --install-ghc to install the correct GHC into " <> T.pack (toFilePath (configLocalPrograms config)) diff --git a/src/main/Main.hs b/src/main/Main.hs index e67fdd2d3e..04431ab657 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -545,7 +545,7 @@ setupCmd SetupCmdOpts{..} go@GlobalOpts{..} = do case scoCompilerVersion of Just v -> return (v, MatchMinor, Nothing) Nothing -> do - bc <- lcLoadBuildConfig lc globalResolver + bc <- lcLoadBuildConfig lc globalResolver globalCompiler return ( bcWantedCompiler bc , configCompilerCheck (lcConfig lc) , Just $ bcStackYaml bc @@ -690,7 +690,7 @@ withBuildConfigExt go@GlobalOpts{..} mbefore inner mafter = do let inner'' lk = do bconfig <- runStackLoggingTGlobal manager go $ - lcLoadBuildConfig lc globalResolver + lcLoadBuildConfig lc globalResolver globalCompiler envConfig <- runStackTGlobal manager bconfig go diff --git a/src/test/Stack/BuildPlanSpec.hs b/src/test/Stack/BuildPlanSpec.hs index bc075189df..a4e28ab69e 100644 --- a/src/test/Stack/BuildPlanSpec.hs +++ b/src/test/Stack/BuildPlanSpec.hs @@ -54,7 +54,7 @@ spec = beforeAll setup $ afterAll teardown $ do -- github still depends on failure. writeFile "stack.yaml" "resolver: lts-2.9" LoadConfig{..} <- loadConfig' manager - bconfig <- loadBuildConfigRest manager (lcLoadBuildConfig Nothing) + bconfig <- loadBuildConfigRest manager (lcLoadBuildConfig Nothing Nothing) runStackT manager logLevel bconfig False False $ do menv <- getMinimalEnvOverride mbp <- loadMiniBuildPlan $ LTS 2 9 diff --git a/src/test/Stack/ConfigSpec.hs b/src/test/Stack/ConfigSpec.hs index 51bb2daad5..31203bc51e 100644 --- a/src/test/Stack/ConfigSpec.hs +++ b/src/test/Stack/ConfigSpec.hs @@ -82,7 +82,7 @@ spec = beforeAll setup $ afterAll teardown $ do setCurrentDirectory childDir LoadConfig{..} <- loadConfig' manager bc@BuildConfig{..} <- loadBuildConfigRest manager - (lcLoadBuildConfig Nothing) + (lcLoadBuildConfig Nothing Nothing) bcRoot bc `shouldBe` parentDir it "respects the STACK_YAML env variable" $ \T{..} -> inTempDir $ do @@ -92,7 +92,7 @@ spec = beforeAll setup $ afterAll teardown $ do withEnvVar "STACK_YAML" stackYamlFp $ do LoadConfig{..} <- loadConfig' manager BuildConfig{..} <- loadBuildConfigRest manager - (lcLoadBuildConfig Nothing) + (lcLoadBuildConfig Nothing Nothing) bcStackYaml `shouldBe` dir stackDotYaml parent bcStackYaml `shouldBe` dir @@ -106,5 +106,5 @@ spec = beforeAll setup $ afterAll teardown $ do withEnvVar "STACK_YAML" (toFilePath yamlRel) $ do LoadConfig{..} <- loadConfig' manager BuildConfig{..} <- loadBuildConfigRest manager - (lcLoadBuildConfig Nothing) + (lcLoadBuildConfig Nothing Nothing) bcStackYaml `shouldBe` yamlAbs From 123e45246645b70ae8805bc509ee2c8824b37d27 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 20 Oct 2015 22:03:13 -0700 Subject: [PATCH 077/106] Remove some debugging on stack exec --- src/main/Main.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/Main.hs b/src/main/Main.hs index 04431ab657..a907d31b1c 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -799,7 +799,6 @@ sdistCmd (dirs, mpvpBounds) go = -- | Execute a command. execCmd :: ExecOpts -> GlobalOpts -> IO () execCmd eo@ExecOpts {..} go@GlobalOpts{..} = do - print eo let needCmdErr = error "You must provide a command to exec, e.g. 'stack exec echo Hello World'" case eoExtra of ExecOptsPlain -> do From e96b3418d560433449eb6cc7f38ae61fa3d6a097 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Wed, 21 Oct 2015 01:44:56 -0700 Subject: [PATCH 078/106] Revert "Use --coverage flag instead of --ghc-options -fhpc" This reverts commit da2f02de07bf877134fab9ba6738230783d1aa11. --- src/Stack/Options.hs | 7 +++++++ src/Stack/Types/Build.hs | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 4b8cbbfc6f..48cfe29817 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -70,10 +70,17 @@ benchOptsParser = BenchmarkOpts <*> switch (long "no-run-benchmarks" <> help "Disable running of benchmarks. (Benchmarks will still be built.)") +addCoverageFlags :: BuildOpts -> BuildOpts +addCoverageFlags bopts + | toCoverage $ boptsTestOpts bopts + = bopts { boptsGhcOptions = "-fhpc" : boptsGhcOptions bopts } + | otherwise = bopts + -- | Parser for build arguments. buildOptsParser :: Command -> Parser BuildOpts buildOptsParser cmd = + fmap addCoverageFlags $ BuildOpts <$> target <*> libProfiling <*> exeProfiling <*> haddock <*> haddockDeps <*> dryRun <*> ghcOpts <*> flags <*> copyBins <*> preFetch <*> buildSubset <*> diff --git a/src/Stack/Types/Build.hs b/src/Stack/Types/Build.hs index 030c4cb31c..94c399ff0a 100644 --- a/src/Stack/Types/Build.hs +++ b/src/Stack/Types/Build.hs @@ -668,7 +668,6 @@ configureOptsNoDir econfig bco deps wanted isLocal package = concat [ depOptions , ["--enable-library-profiling" | boptsLibProfile bopts || boptsExeProfile bopts] , ["--enable-executable-profiling" | boptsExeProfile bopts] - , ["--coverage" | toCoverage (boptsTestOpts bopts)] , map (\(name,enabled) -> "-f" <> (if enabled From 73272557287fedad1d3f6f9bc4c73319871c1717 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Wed, 21 Oct 2015 02:10:00 -0700 Subject: [PATCH 079/106] Fix a warning --- src/main/Main.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/Main.hs b/src/main/Main.hs index a907d31b1c..a874d706fb 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -798,7 +798,7 @@ sdistCmd (dirs, mpvpBounds) go = -- | Execute a command. execCmd :: ExecOpts -> GlobalOpts -> IO () -execCmd eo@ExecOpts {..} go@GlobalOpts{..} = do +execCmd ExecOpts {..} go@GlobalOpts{..} = do let needCmdErr = error "You must provide a command to exec, e.g. 'stack exec echo Hello World'" case eoExtra of ExecOptsPlain -> do From d4aeaa93cb193bb541b0ee2493a8e5f2cda9a167 Mon Sep 17 00:00:00 2001 From: mwu Date: Wed, 21 Oct 2015 11:13:54 +0200 Subject: [PATCH 080/106] When looking for GHC to compile Setup.hs, local extra bin directories should not be included (#1052). --- src/Stack/Build/Execute.hs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 050bd62932..024f817ab4 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -692,14 +692,18 @@ withSingleContext runInBase ActionContext {..} ExecuteEnv {..} task@Task {..} md withCabal package pkgDir mlogFile inner = do config <- asks getConfig - menv <- liftIO $ configEnvOverride config EnvSettings - { esIncludeLocals = taskLocation task == Local - , esIncludeGhcPackagePath = False - , esStackExe = False - , esLocaleUtf8 = True - } - getGhcPath <- runOnce $ liftIO $ join $ findExecutable menv "ghc" - getGhcjsPath <- runOnce $ liftIO $ join $ findExecutable menv "ghcjs" + let envSettings = EnvSettings + { esIncludeLocals = taskLocation task == Local + , esIncludeGhcPackagePath = False + , esStackExe = False + , esLocaleUtf8 = True + } + menv <- liftIO $ configEnvOverride config envSettings + -- When looking for ghc to build Setup.hs we want to ignore local binaries, see: + -- https://github.com/commercialhaskell/stack/issues/1052 + menvWithoutLocals <- liftIO $ configEnvOverride config envSettings { esIncludeLocals = False } + getGhcPath <- runOnce $ liftIO $ join $ findExecutable menvWithoutLocals "ghc" + getGhcjsPath <- runOnce $ liftIO $ join $ findExecutable menvWithoutLocals "ghcjs" distRelativeDir' <- distRelativeDir esetupexehs <- -- Avoid broken Setup.hs files causing problems for simple build From 226f51c2f24a47a2377c8d41edd264ba11dba131 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Wed, 21 Oct 2015 09:33:59 +0000 Subject: [PATCH 081/106] Mark some GHC options as important regardless of configuration --- src/Stack/Build/ConstructPlan.hs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 3b2e47ef0d..d44436afab 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -5,6 +5,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} +{-# LANGUAGE ViewPatterns #-} -- | Construct a @Plan@ for how to build module Stack.Build.ConstructPlan ( constructPlan @@ -536,16 +537,25 @@ describeConfigDiff config old new go where go [] = [] - go ("--ghc-option":_:xs) = go xs - go ("--ghc-options":_:xs) = go xs - go (x:xs) - | isPrefixed x = go xs - | otherwise = x : go xs - - isPrefixed t = any (`T.isPrefixOf` t) - [ "--ghc-option=" - , "--ghc-options=" - ] + go ("--ghc-option":x:xs) = go' x xs + go ("--ghc-options":x:xs) = go' x xs + go ((T.stripPrefix "--ghc-option" -> Just x):xs) = go' x xs + go ((T.stripPrefix "--ghc-options" -> Just x):xs) = go' x xs + go (x:xs) = x : go xs + + go' x xs = checkKeepers x $ go xs + + checkKeepers x xs = + case filter isKeeper $ T.words x of + [] -> xs + keepers -> "--ghc-options" : T.unwords keepers : xs + + -- GHC options which affect build results and therefore should always + -- force a rebuild + -- + -- For the most part, we only care about options generated by Stack + -- itself + isKeeper = (== "-fhpc") -- more to be added later userOpts = filter (not . isStackOpt) . (if configRebuildGhcOptions config From 4797dedd12aedc661697625549c52de8d335ffaf Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Wed, 21 Oct 2015 03:34:56 -0700 Subject: [PATCH 082/106] Hack to make GHCJS work with stackage #1190 --- ChangeLog.md | 1 + src/Stack/Build/Installed.hs | 146 ++++++++++++++++++++++++----------- src/Stack/Constants.hs | 48 ++++++++++++ 3 files changed, 150 insertions(+), 45 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0b2c82c7f3..c97c2a747d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,7 @@ Major changes: +* GHCJS can now be used with stackage snapshots. * Windows installers are now available: [download them here](https://github.com/commercialhaskell/stack/blob/release/doc/install_and_upgrade.md#windows) [#613](https://github.com/commercialhaskell/stack/issues/613) diff --git a/src/Stack/Build/Installed.hs b/src/Stack/Build/Installed.hs index c1b962453a..b7dff7528c 100644 --- a/src/Stack/Build/Installed.hs +++ b/src/Stack/Build/Installed.hs @@ -28,11 +28,14 @@ import Data.Map.Strict (Map) import qualified Data.Map.Strict as M import qualified Data.Map.Strict as Map import Data.Maybe +import Data.Monoid +import qualified Data.Text as T import Network.HTTP.Client.Conduit (HasHttpManager) import Path import Prelude hiding (FilePath, writeFile) import Stack.Build.Cache import Stack.Types.Build +import Stack.Types.Version import Stack.Constants import Stack.GhcPkg import Stack.PackageDump @@ -41,13 +44,6 @@ import Stack.Types.Internal type M env m = (MonadIO m,MonadReader env m,HasHttpManager env,HasEnvConfig env,MonadLogger m,MonadBaseControl IO m,MonadCatch m,MonadMask m,HasLogLevel env) -data LoadHelper = LoadHelper - { lhId :: !GhcPkgId - , lhDeps :: ![GhcPkgId] - , lhPair :: !(PackageName, (InstallLocation, Installed)) - } - deriving Show - -- | Options for 'getInstalled'. data GetInstalledOpts = GetInstalledOpts { getInstalledProfiling :: !Bool @@ -83,7 +79,7 @@ getInstalled menv opts sourceMap = do (installedLibs1, _extraInstalled) <- (foldM (\lhs' pkgdb -> do lhs'' <- loadDatabase' (Just (ExtraGlobal, pkgdb)) (fst lhs') - return lhs'') ((installedLibs0, globalInstalled)) extraDBPaths) + return lhs'') (installedLibs0, globalInstalled) extraDBPaths) (installedLibs2, _snapInstalled) <- loadDatabase' (Just (InstalledTo Snap, snapDBPath)) installedLibs1 (installedLibs3, localInstalled) <- @@ -136,9 +132,10 @@ loadDatabase :: (M env m, PackageInstallInfo pii) -> m ([LoadHelper], [DumpPackage () ()]) loadDatabase menv opts mcache sourceMap mdb lhs0 = do wc <- getWhichCompiler - (lhs1, dps) <- ghcPkgDump menv wc (fmap snd (maybeToList mdb)) + (lhs1', dps) <- ghcPkgDump menv wc (fmap snd (maybeToList mdb)) $ conduitDumpPackage =$ sink - + let ghcjsHack = wc == Ghcjs && isNothing mdb + lhs1 <- liftM catMaybes $ mapM (processLoadResult mdb ghcjsHack) lhs1' let lhs = pruneDeps id lhId @@ -159,14 +156,65 @@ loadDatabase menv opts mcache sourceMap mdb lhs0 = do -- Just an optimization to avoid calculating the haddock -- values when they aren't necessary _ -> CL.map (\dp -> dp { dpHaddock = False }) + mloc = fmap fst mdb sinkDP = conduitProfilingCache =$ conduitHaddockCache - =$ CL.mapMaybe (isAllowed opts mcache sourceMap (fmap fst mdb)) + =$ CL.map (\dp -> (isAllowed opts mcache sourceMap mloc dp, toLoadHelper mloc dp)) =$ CL.consume sink = getZipSink $ (,) <$> ZipSink sinkDP <*> ZipSink CL.consume +processLoadResult :: MonadLogger m + => Maybe (InstalledPackageLocation, Path Abs Dir) + -> Bool + -> (Allowed, LoadHelper) + -> m (Maybe LoadHelper) +processLoadResult _ _ (Allowed, lh) = return (Just lh) +processLoadResult _ True (WrongVersion actual wanted, lh) + -- Allow some packages in the ghcjs global DB to have the wrong + -- versions. Treat them as wired-ins by setting deps to []. + | fst (lhPair lh) `HashSet.member` ghcjsBootPackages = do + $logWarn $ T.concat + [ "Ignoring that the GHCJS boot package \"" + , packageNameText (fst (lhPair lh)) + , "\" has a different version, " + , versionText actual + , ", than the resolver's wanted version, " + , versionText wanted + ] + return (Just lh) +processLoadResult mdb _ (reason, lh) = do + $logDebug $ T.concat $ + [ "Ignoring package " + , packageNameText (fst (lhPair lh)) + ] ++ + (maybe [] (\db -> [", from ", T.pack (show db), ","]) mdb) ++ + [ " due to " + , case reason of + Allowed -> " the impossible?!?!" + NeedsProfiling -> " it needing profiling." + NeedsHaddock -> " it needing haddocks." + UnknownPkg -> " it being unknown to the resolver / extra-deps." + WrongLocation mloc loc -> " wrong location: " <> T.pack (show (mloc, loc)) + WrongVersion actual wanted -> T.concat $ + [ " wanting version " + , versionText wanted + , " instead of " + , versionText actual + ] + ] + return Nothing + +data Allowed + = Allowed + | NeedsProfiling + | NeedsHaddock + | UnknownPkg + | WrongLocation (Maybe InstalledPackageLocation) InstallLocation + | WrongVersion Version Version + deriving (Eq, Show) + -- | Check if a can be included in the set of installed packages or not, based -- on the package selections made by the user. This does not perform any -- dirtiness or flag change checks. @@ -176,54 +224,62 @@ isAllowed :: PackageInstallInfo pii -> Map PackageName pii -> Maybe InstalledPackageLocation -> DumpPackage Bool Bool - -> Maybe LoadHelper + -> Allowed isAllowed opts mcache sourceMap mloc dp -- Check that it can do profiling if necessary - | getInstalledProfiling opts && isJust mcache && not (dpProfiling dp) = Nothing + | getInstalledProfiling opts && isJust mcache && not (dpProfiling dp) = NeedsProfiling -- Check that it has haddocks if necessary - | getInstalledHaddock opts && isJust mcache && not (dpHaddock dp) = Nothing - | toInclude = Just LoadHelper - { lhId = gid - , lhDeps = - -- We always want to consider the wired in packages as having all - -- of their dependencies installed, since we have no ability to - -- reinstall them. This is especially important for using different - -- minor versions of GHC, where the dependencies of wired-in - -- packages may change slightly and therefore not match the - -- snapshot. - if name `HashSet.member` wiredInPackages - then [] - else dpDepends dp - , lhPair = (name, (toPackageLocation mloc, Library ident gid)) - } - | otherwise = Nothing - where - toPackageLocation :: Maybe InstalledPackageLocation -> InstallLocation - toPackageLocation Nothing = Snap - toPackageLocation (Just ExtraGlobal) = Snap - toPackageLocation (Just (InstalledTo loc)) = loc - - toInclude = + | getInstalledHaddock opts && isJust mcache && not (dpHaddock dp) = NeedsHaddock + | otherwise = case Map.lookup name sourceMap of Nothing -> case mloc of -- The sourceMap has nothing to say about this global -- package, so we can use it - Nothing -> True - Just ExtraGlobal -> True + Nothing -> Allowed + Just ExtraGlobal -> Allowed -- For non-global packages, don't include unknown packages. -- See: -- https://github.com/commercialhaskell/stack/issues/292 - Just _ -> False - - Just pii -> - version == piiVersion pii -- only accept the desired version - && checkLocation (piiLocation pii) - + Just _ -> UnknownPkg + Just pii + | not (checkLocation (piiLocation pii)) -> WrongLocation mloc (piiLocation pii) + | version /= piiVersion pii -> WrongVersion version (piiVersion pii) + | otherwise -> Allowed + where + PackageIdentifier name version = dpPackageIdent dp -- Ensure that the installed location matches where the sourceMap says it -- should be installed checkLocation Snap = mloc /= Just (InstalledTo Local) -- we can allow either global or snap checkLocation Local = mloc == Just (InstalledTo Local) || mloc == Just ExtraGlobal -- 'locally' installed snapshot packages can come from extra dbs +data LoadHelper = LoadHelper + { lhId :: !GhcPkgId + , lhDeps :: ![GhcPkgId] + , lhPair :: !(PackageName, (InstallLocation, Installed)) + } + deriving Show + +toLoadHelper :: Maybe InstalledPackageLocation -> DumpPackage Bool Bool -> LoadHelper +toLoadHelper mloc dp = LoadHelper + { lhId = gid + , lhDeps = + -- We always want to consider the wired in packages as having all + -- of their dependencies installed, since we have no ability to + -- reinstall them. This is especially important for using different + -- minor versions of GHC, where the dependencies of wired-in + -- packages may change slightly and therefore not match the + -- snapshot. + if name `HashSet.member` wiredInPackages + then [] + else dpDepends dp + , lhPair = (name, (toPackageLocation mloc, Library ident gid)) + } + where gid = dpGhcPkgId dp - ident@(PackageIdentifier name version) = dpPackageIdent dp + ident@(PackageIdentifier name _) = dpPackageIdent dp + +toPackageLocation :: Maybe InstalledPackageLocation -> InstallLocation +toPackageLocation Nothing = Snap +toPackageLocation (Just ExtraGlobal) = Snap +toPackageLocation (Just (InstalledTo loc)) = loc diff --git a/src/Stack/Constants.hs b/src/Stack/Constants.hs index 806aa3b803..7be5ef1683 100644 --- a/src/Stack/Constants.hs +++ b/src/Stack/Constants.hs @@ -25,6 +25,7 @@ module Stack.Constants ,benchBuiltFile ,stackProgName ,wiredInPackages + ,ghcjsBootPackages ,cabalPackageName ,implicitGlobalProjectDirDeprecated ,implicitGlobalProjectDir @@ -283,6 +284,53 @@ wiredInPackages = , "interactive" ] +-- TODO: Get this unwieldy list out of here and into a datafile +-- generated by GHCJS! See https://github.com/ghcjs/ghcjs/issues/434 +ghcjsBootPackages :: HashSet PackageName +ghcjsBootPackages = + maybe (error "Parse error in ghcjsBootPackages") HashSet.fromList mparsed + where + mparsed = sequence $ map parsePackageName + -- stage1a + [ "array" + , "base" + , "binary" + , "bytestring" + , "containers" + , "deepseq" + , "integer-gmp" + , "pretty" + , "primitive" + , "integer-gmp" + , "pretty" + , "primitive" + , "template-haskell" + , "transformers" + -- stage1b + , "directory" + , "filepath" + , "old-locale" + , "process" + , "time" + -- stage2 + , "async" + , "aeson" + , "attoparsec" + , "case-insensitive" + , "dlist" + , "extensible-exceptions" + , "hashable" + , "mtl" + , "old-time" + , "parallel" + , "scientific" + , "stm" + , "syb" + , "text" + , "unordered-containers" + , "vector" + ] + -- | Just to avoid repetition and magic strings. cabalPackageName :: PackageName cabalPackageName = From edba97514af166cd37be138ef2151e42b7ff99d1 Mon Sep 17 00:00:00 2001 From: Chris Done Date: Tue, 20 Oct 2015 18:45:57 +0200 Subject: [PATCH 083/106] Accept a template referring to local files (#1095) --- src/Stack/New.hs | 19 +++++++++++++------ src/Stack/Options.hs | 3 ++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Stack/New.hs b/src/Stack/New.hs index cbc0aff629..dfd05ba385 100644 --- a/src/Stack/New.hs +++ b/src/Stack/New.hs @@ -115,12 +115,19 @@ loadTemplate name = do req <- parseUrl (defaultTemplateUrl <> "/" <> toFilePath (templatePath name)) config <- asks getConfig - let path = templatesDir config templatePath name - _ <- catch (redownload req path) (throwM . FailedToDownloadTemplate name) - exists <- fileExists path - if exists - then liftIO (T.readFile (toFilePath path)) - else throwM (FailedToLoadTemplate name path) + localExists <- fileExists . templatePath $ name + if localExists + then liftIO . T.readFile . toFilePath . templatePath $ name + else do + let path = templatesDir config templatePath name + _ <- + catch + (redownload req path) + (throwM . FailedToDownloadTemplate name) + exists <- fileExists path + if exists + then liftIO (T.readFile (toFilePath path)) + else throwM (FailedToLoadTemplate name path) -- | Apply and unpack a template into a directory. applyTemplate diff --git a/src/Stack/Options.hs b/src/Stack/Options.hs index 48cfe29817..7105710848 100644 --- a/src/Stack/Options.hs +++ b/src/Stack/Options.hs @@ -695,7 +695,8 @@ newOptsParser = (,) <$> newOpts <*> initOptsParser help "Do not create a subdirectory for the project") <*> templateNameArgument (metavar "TEMPLATE_NAME" <> - help "Name of a template, for example: foo or foo.hsfiles" <> + help "Name of a template or a local template in a subdirectory,\ + \ for example: foo or foo.hsfiles" <> value defaultTemplateName) <*> fmap M.fromList From c6831162fd108463b39b317f662f01742d176a9a Mon Sep 17 00:00:00 2001 From: Chris Done Date: Wed, 21 Oct 2015 14:50:57 +0200 Subject: [PATCH 084/106] Accept relative or absolute template files (#1095) --- src/Stack/New.hs | 53 ++++++++++++++++++++------------- src/Stack/Types/TemplateName.hs | 23 +++++++++----- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/Stack/New.hs b/src/Stack/New.hs index dfd05ba385..e927225b1a 100644 --- a/src/Stack/New.hs +++ b/src/Stack/New.hs @@ -109,25 +109,38 @@ new opts = do -- | Download and read in a template's text content. loadTemplate - :: (HasConfig r, HasHttpManager r, MonadReader r m, MonadIO m, MonadThrow m, MonadCatch m) + :: forall m r. + (HasConfig r, HasHttpManager r, MonadReader r m, MonadIO m, MonadThrow m, MonadCatch m) => TemplateName -> m Text -loadTemplate name = do - req <- - parseUrl (defaultTemplateUrl <> "/" <> toFilePath (templatePath name)) - config <- asks getConfig - localExists <- fileExists . templatePath $ name - if localExists - then liftIO . T.readFile . toFilePath . templatePath $ name - else do - let path = templatesDir config templatePath name - _ <- - catch - (redownload req path) - (throwM . FailedToDownloadTemplate name) - exists <- fileExists path - if exists - then liftIO (T.readFile (toFilePath path)) - else throwM (FailedToLoadTemplate name path) +loadTemplate name = + case templatePath name of + Left absFile -> loadLocalFile absFile + Right relFile -> + catch + (loadLocalFile relFile) + (\(_ :: NewException) -> + downloadTemplate relFile) + where + loadLocalFile :: Path b File -> m Text + loadLocalFile path = do + exists <- fileExists path + if exists + then liftIO (T.readFile (toFilePath path)) + else throwM (FailedToLoadTemplate name (toFilePath path)) + downloadTemplate :: Path Rel File -> m Text + downloadTemplate rel = do + config <- asks getConfig + req <- parseUrl (defaultTemplateUrl <> "/" <> toFilePath rel) + let path :: Path Abs File + path = templatesDir config rel + _ <- + catch + (redownload req path) + (throwM . FailedToDownloadTemplate name) + exists <- fileExists path + if exists + then liftIO (T.readFile (toFilePath path)) + else throwM (FailedToLoadTemplate name (toFilePath path)) -- | Apply and unpack a template into a directory. applyTemplate @@ -276,7 +289,7 @@ defaultTemplatesList = -- | Exception that might occur when making a new project. data NewException = FailedToLoadTemplate !TemplateName - !(Path Abs File) + !FilePath | FailedToDownloadTemplate !TemplateName !DownloadException | FailedToDownloadTemplates !HttpException @@ -292,7 +305,7 @@ instance Show NewException where show (FailedToLoadTemplate name path) = "Failed to load download template " <> T.unpack (templateName name) <> " from " <> - toFilePath path + path show (FailedToDownloadTemplate name (RedownloadFailed _ _ resp)) = case statusCode (responseStatus resp) of 404 -> diff --git a/src/Stack/Types/TemplateName.hs b/src/Stack/Types/TemplateName.hs index b71752d0e6..66da7058f1 100644 --- a/src/Stack/Types/TemplateName.hs +++ b/src/Stack/Types/TemplateName.hs @@ -15,12 +15,12 @@ import qualified Options.Applicative as O import Path import Path.Internal --- | A template name of the format @foo.hsfiles@. -data TemplateName = TemplateName !Text !(Path Rel File) +-- | A template name. +data TemplateName = TemplateName !Text !(Either (Path Abs File) (Path Rel File)) deriving (Ord,Eq,Show) -- | An argument which accepts a template name of the format --- @foo.hsfiles@ or @foo@, ultimately normalized to @foo.hsfiles@. +-- @foo.hsfiles@ or @foo@, ultimately normalized to @foo@. templateNameArgument :: O.Mod O.ArgumentFields TemplateName -> O.Parser TemplateName templateNameArgument = @@ -51,8 +51,11 @@ parseTemplateNameFromString fname = where parseValidFile prefix str = case parseRelFile str of - Nothing -> Left expected - Just fp -> return (TemplateName prefix fp) + Nothing -> + case parseAbsFile str of + Nothing -> Left expected + Just fp -> return (TemplateName prefix (Left fp)) + Just fp -> return (TemplateName prefix (Right fp)) expected = "Expected a template filename like: foo or foo.hsfiles" -- | Make a template name. @@ -60,13 +63,17 @@ mkTemplateName :: String -> Q Exp mkTemplateName s = case parseTemplateNameFromString s of Left{} -> error ("Invalid template name: " ++ show s) - Right (TemplateName (T.unpack -> prefix) (Path pn)) -> - [|TemplateName (T.pack prefix) (Path pn)|] + Right (TemplateName (T.unpack -> prefix) p) -> + [|TemplateName (T.pack prefix) $(pn)|] + where pn = + case p of + Left (Path fp) -> [|Left (Path fp)|] + Right (Path fp) -> [|Right (Path fp)|] -- | Get a text representation of the template name. templateName :: TemplateName -> Text templateName (TemplateName prefix _) = prefix -- | Get the path of the template. -templatePath :: TemplateName -> Path Rel File +templatePath :: TemplateName -> Either (Path Abs File) (Path Rel File) templatePath (TemplateName _ fp) = fp From b308d378b76ae9874838c51a7a161596e9d69c2e Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Fri, 23 Oct 2015 01:32:58 +0000 Subject: [PATCH 085/106] Add missing = (thanks @sjakobi) --- src/Stack/Build/ConstructPlan.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index d44436afab..16127f9063 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -539,8 +539,8 @@ describeConfigDiff config old new go [] = [] go ("--ghc-option":x:xs) = go' x xs go ("--ghc-options":x:xs) = go' x xs - go ((T.stripPrefix "--ghc-option" -> Just x):xs) = go' x xs - go ((T.stripPrefix "--ghc-options" -> Just x):xs) = go' x xs + go ((T.stripPrefix "--ghc-option=" -> Just x):xs) = go' x xs + go ((T.stripPrefix "--ghc-options=" -> Just x):xs) = go' x xs go (x:xs) = x : go xs go' x xs = checkKeepers x $ go xs From ac6c9e12816b9b6db488e40d02a6b55f94b3b7f1 Mon Sep 17 00:00:00 2001 From: Tristan Webb Date: Mon, 19 Oct 2015 19:14:46 -0700 Subject: [PATCH 086/106] Refactoring config monoid names to top-level decls --- src/Stack/Types/Config.hs | 159 ++++++++++++++++++++++++++++++-------- 1 file changed, 127 insertions(+), 32 deletions(-) diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index c53c34d2c3..9d0ae235e6 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -705,58 +705,57 @@ instance FromJSON (ConfigMonoid, [JSONWarning]) where -- warnings for missing fields. parseConfigMonoidJSON :: Object -> WarningParser ConfigMonoid parseConfigMonoidJSON obj = do - configMonoidDockerOpts <- jsonSubWarnings (obj ..:? "docker" ..!= mempty) - configMonoidConnectionCount <- obj ..:? "connection-count" - configMonoidHideTHLoading <- obj ..:? "hide-th-loading" - configMonoidLatestSnapshotUrl <- obj ..:? "latest-snapshot-url" - configMonoidPackageIndices <- jsonSubWarningsTT (obj ..:? "package-indices") - configMonoidSystemGHC <- obj ..:? "system-ghc" - configMonoidInstallGHC <- obj ..:? "install-ghc" - configMonoidSkipGHCCheck <- obj ..:? "skip-ghc-check" - configMonoidSkipMsys <- obj ..:? "skip-msys" + configMonoidDockerOpts <- jsonSubWarnings (obj ..:? configMonoidDockerOptsName ..!= mempty) + configMonoidConnectionCount <- obj ..:? configMonoidConnectionCountName + configMonoidHideTHLoading <- obj ..:? configMonoidHideTHLoadingName + configMonoidLatestSnapshotUrl <- obj ..:? configMonoidLatestSnapshotUrlName + configMonoidPackageIndices <- jsonSubWarningsTT (obj ..:? configMonoidPackageIndicesName) + configMonoidSystemGHC <- obj ..:? configMonoidSystemGHCName + configMonoidInstallGHC <- obj ..:? configMonoidInstallGHCName + configMonoidSkipGHCCheck <- obj ..:? configMonoidSkipGHCCheckName + configMonoidSkipMsys <- obj ..:? configMonoidSkipMsysName configMonoidRequireStackVersion <- unVersionRangeJSON <$> - obj ..:? "require-stack-version" + obj ..:? configMonoidRequireStackVersionName ..!= VersionRangeJSON anyVersion - configMonoidOS <- obj ..:? "os" - configMonoidArch <- obj ..:? "arch" - configMonoidGHCVariant <- obj ..:? "ghc-variant" - configMonoidJobs <- obj ..:? "jobs" - configMonoidExtraIncludeDirs <- obj ..:? "extra-include-dirs" ..!= Set.empty - configMonoidExtraLibDirs <- obj ..:? "extra-lib-dirs" ..!= Set.empty - configMonoidConcurrentTests <- obj ..:? "concurrent-tests" - configMonoidLocalBinPath <- obj ..:? "local-bin-path" - configMonoidImageOpts <- jsonSubWarnings (obj ..:? "image" ..!= mempty) + configMonoidOS <- obj ..:? configMonoidOSName + configMonoidArch <- obj ..:? configMonoidArchName + configMonoidGHCVariant <- obj ..:? configMonoidGHCVariantName + configMonoidJobs <- obj ..:? configMonoidJobsName + configMonoidExtraIncludeDirs <- obj ..:? configMonoidExtraIncludeDirsName ..!= Set.empty + configMonoidExtraLibDirs <- obj ..:? configMonoidExtraLibDirsName ..!= Set.empty + configMonoidConcurrentTests <- obj ..:? configMonoidConcurrentTestsName + configMonoidLocalBinPath <- obj ..:? configMonoidLocalBinPathName + configMonoidImageOpts <- jsonSubWarnings (obj ..:? configMonoidImageOptsName ..!= mempty) templates <- obj ..:? "templates" (configMonoidScmInit,configMonoidTemplateParameters) <- case templates of Nothing -> return (Nothing,M.empty) Just tobj -> do - scmInit <- tobj ..:? "scm-init" - params <- tobj ..:? "params" + scmInit <- tobj ..:? configMonoidScmInitName + params <- tobj ..:? configMonoidTemplateParametersName return (scmInit,fromMaybe M.empty params) - configMonoidCompilerCheck <- obj ..:? "compiler-check" + configMonoidCompilerCheck <- obj ..:? configMonoidCompilerCheckName - mghcoptions <- obj ..:? "ghc-options" + mghcoptions <- obj ..:? configMonoidGhcOptionsName configMonoidGhcOptions <- case mghcoptions of Nothing -> return mempty Just m -> fmap Map.fromList $ mapM handleGhcOptions $ Map.toList m - extraPath <- obj ..:? "extra-path" ..!= [] + extraPath <- obj ..:? configMonoidExtraPathName ..!= [] configMonoidExtraPath <- forM extraPath $ either (fail . show) return . parseAbsDir . T.unpack configMonoidSetupInfoLocations <- - maybeToList <$> jsonSubWarningsT (obj ..:? "setup-info") - - configMonoidPvpBounds <- obj ..:? "pvp-bounds" - configMonoidModifyCodePage <- obj ..:? "modify-code-page" + maybeToList <$> jsonSubWarningsT (obj ..:? configMonoidSetupInfoLocationsName) + configMonoidPvpBounds <- obj ..:? configMonoidPvpBoundsName + configMonoidModifyCodePage <- obj ..:? configMonoidModifyCodePageName configMonoidExplicitSetupDeps <- - (obj ..:? "explicit-setup-deps" ..!= mempty) + (obj ..:? configMonoidExplicitSetupDepsName ..!= mempty) >>= fmap Map.fromList . mapM handleExplicitSetupDep . Map.toList - configMonoidRebuildGhcOptions <- obj ..:? "rebuild-ghc-options" - configMonoidApplyGhcOptions <- obj ..:? "apply-ghc-options" - configMonoidAllowNewer <- obj ..:? "allow-newer" + configMonoidRebuildGhcOptions <- obj ..:? configMonoidRebuildGhcOptionsName + configMonoidApplyGhcOptions <- obj ..:? configMonoidApplyGhcOptionsName + configMonoidAllowNewer <- obj ..:? configMonoidAllowNewerName return ConfigMonoid {..} where @@ -783,6 +782,102 @@ parseConfigMonoidJSON obj = do Right x -> return $ Just x return (name, b) +configMonoidDockerOptsName :: Text +configMonoidDockerOptsName = "docker" + +configMonoidConnectionCountName :: Text +configMonoidConnectionCountName = "connection-count" + +configMonoidHideTHLoadingName :: Text +configMonoidHideTHLoadingName = "hide-th-loading" + +configMonoidLatestSnapshotUrlName :: Text +configMonoidLatestSnapshotUrlName = "latest-snapshot-url" + +configMonoidPackageIndicesName :: Text +configMonoidPackageIndicesName = "package-indices" + +configMonoidSystemGHCName :: Text +configMonoidSystemGHCName = "system-ghc" + +configMonoidInstallGHCName :: Text +configMonoidInstallGHCName = "install-ghc" + +configMonoidSkipGHCCheckName :: Text +configMonoidSkipGHCCheckName = "skip-ghc-check" + +configMonoidSkipMsysName :: Text +configMonoidSkipMsysName = "skip-msys" + +configMonoidRequireStackVersionName :: Text +configMonoidRequireStackVersionName = "require-stack-version" + +configMonoidOSName :: Text +configMonoidOSName = "os" + +configMonoidArchName :: Text +configMonoidArchName = "arch" + +configMonoidGHCVariantName :: Text +configMonoidGHCVariantName = "ghc-variant" + +configMonoidJobsName :: Text +configMonoidJobsName = "jobs" + +configMonoidExtraIncludeDirsName :: Text +configMonoidExtraIncludeDirsName = "extra-include-dirs" + +configMonoidExtraLibDirsName :: Text +configMonoidExtraLibDirsName = "extra-lib-dirs" + +configMonoidConcurrentTestsName :: Text +configMonoidConcurrentTestsName = "concurrent-tests" + +configMonoidLocalBinPathName :: Text +configMonoidLocalBinPathName = "local-bin-path" + +configMonoidImageOptsName :: Text +configMonoidImageOptsName = "image" + +configMonoidTemplatesName :: Text +configMonoidTemplatesName = "templates" + +configMonoidScmInitName :: Text +configMonoidScmInitName = "scm-init" + +configMonoidTemplateParametersName :: Text +configMonoidTemplateParametersName = "params" + +configMonoidCompilerCheckName :: Text +configMonoidCompilerCheckName = "compiler-check" + +configMonoidGhcOptionsName :: Text +configMonoidGhcOptionsName = "ghc-options" + +configMonoidExtraPathName :: Text +configMonoidExtraPathName = "extra-path" + +configMonoidSetupInfoLocationsName :: Text +configMonoidSetupInfoLocationsName = "setup-info" + +configMonoidPvpBoundsName :: Text +configMonoidPvpBoundsName = "pvp-bounds" + +configMonoidModifyCodePageName :: Text +configMonoidModifyCodePageName = "modify-code-page" + +configMonoidExplicitSetupDepsName :: Text +configMonoidExplicitSetupDepsName = "explicit-setup-deps" + +configMonoidRebuildGhcOptionsName :: Text +configMonoidRebuildGhcOptionsName = "rebuild-ghc-options" + +configMonoidApplyGhcOptionsName :: Text +configMonoidApplyGhcOptionsName = "apply-ghc-options" + +configMonoidAllowNewerName :: Text +configMonoidAllowNewerName = "allow-newer" + -- | Newtype for non-orphan FromJSON instance. newtype VersionRangeJSON = VersionRangeJSON { unVersionRangeJSON :: VersionRange } From b40f1a51a8dafff32b46fd40039dd0d5a84b25a6 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sun, 18 Oct 2015 05:50:50 -0700 Subject: [PATCH 087/106] Remove redundant Version from InstalledMap --- src/Stack/Build/ConstructPlan.hs | 17 ++++++++--------- src/Stack/Build/Execute.hs | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 16127f9063..94b1a77353 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -73,7 +73,7 @@ combineMap = Map.mergeWithKey data AddDepRes = ADRToInstall Task - | ADRFound InstallLocation Version Installed + | ADRFound InstallLocation Installed deriving Show data W = W @@ -158,7 +158,7 @@ constructPlan mbp0 baseConfigOpts0 locals extraToBuild0 locallyRegistered loadPa errs = errlibs ++ errfinals if null errs then do - let toTask (_, ADRFound _ _ _) = Nothing + let toTask (_, ADRFound _ _) = Nothing toTask (name, ADRToInstall task) = Just (name, task) tasks = M.fromList $ mapMaybe toTask adrs takeSubset = @@ -284,9 +284,8 @@ addDep'' treatAsDep name = do -- recommendation available Nothing -> return $ Left $ UnknownPackage name Just (PIOnlyInstalled loc installed) -> do - let version = installedVersion installed - tellExecutablesUpstream name version loc Map.empty -- slightly hacky, no flags since they likely won't affect executable names - return $ Right $ ADRFound loc version installed + tellExecutablesUpstream name (installedVersion installed) loc Map.empty -- slightly hacky, no flags since they likely won't affect executable names + return $ Right $ ADRFound loc installed Just (PIOnlySource ps) -> do tellExecutables name ps installPackage treatAsDep name ps @@ -295,7 +294,7 @@ addDep'' treatAsDep name = do needInstall <- checkNeedInstall treatAsDep name ps installed (wanted ctx) if needInstall then installPackage treatAsDep name ps - else return $ Right $ ADRFound (piiLocation ps) (piiVersion ps) installed + else return $ Right $ ADRFound (piiLocation ps) installed tellExecutables :: PackageName -> PackageSource -> M () -- TODO merge this with addFinal above? tellExecutables _ (PSLocal lp) @@ -441,9 +440,9 @@ addPackageDeps treatAsDep package = do then case adr of ADRToInstall task -> return $ Right (Set.singleton $ taskProvides task, Map.empty, taskLocation task) - ADRFound loc _ (Executable _) -> return $ Right + ADRFound loc (Executable _) -> return $ Right (Set.empty, Map.empty, loc) - ADRFound loc _ (Library ident gid) -> return $ Right + ADRFound loc (Library ident gid) -> return $ Right (Set.empty, Map.singleton ident gid, loc) else return $ Left (depname, (range, mlatest, DependencyMismatch $ adrVersion adr)) case partitionEithers deps of @@ -455,7 +454,7 @@ addPackageDeps treatAsDep package = do (Map.fromList errs) where adrVersion (ADRToInstall task) = packageIdentifierVersion $ taskProvides task - adrVersion (ADRFound _ v _) = v + adrVersion (ADRFound _ installed) = installedVersion installed checkDirtiness :: PackageSource -> Installed diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 024f817ab4..a946ae7de4 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1062,7 +1062,7 @@ depsPresent :: InstalledMap -> Map PackageName VersionRange -> Bool depsPresent installedMap deps = all (\(name, range) -> case Map.lookup name installedMap of - Just (_, installed) -> (installedVersion installed) `withinRange` range + Just (_, installed) -> installedVersion installed `withinRange` range Nothing -> False) (Map.toList deps) From 3baa6b2765f6dd52e80d6d040532f5c7d3bb1a9e Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sat, 24 Oct 2015 15:07:38 -0700 Subject: [PATCH 088/106] Fix: Haddocks not copied for dependencies (fixes #1105) Refactors and optimizes getting `ghc-pkg describe` data for packages as they're installed. --- src/Stack/Build.hs | 8 +- src/Stack/Build/ConstructPlan.hs | 8 +- src/Stack/Build/Execute.hs | 86 ++++++++++++------ src/Stack/Build/Haddock.hs | 143 ++++++++++++++++++++---------- src/Stack/Build/Installed.hs | 17 ++-- src/Stack/Dot.hs | 6 +- src/Stack/GhcPkg.hs | 111 +---------------------- src/Stack/Ghci.hs | 2 +- src/Stack/PackageDump.hs | 33 ++++++- src/Stack/SDist.hs | 4 +- src/test/Stack/PackageDumpSpec.hs | 3 + stack-7.8.yaml | 1 + 12 files changed, 216 insertions(+), 206 deletions(-) diff --git a/src/Stack/Build.hs b/src/Stack/Build.hs index a760ec68f9..abbce03929 100644 --- a/src/Stack/Build.hs +++ b/src/Stack/Build.hs @@ -87,7 +87,7 @@ build setLocalFiles mbuildLk bopts = fixCodePage' $ do $ Set.unions $ map lpFiles locals - (installedMap, globallyRegistered, locallyRegistered) <- + (installedMap, globalDumpPkgs, snapshotDumpPkgs, localDumpPkgs) <- getInstalled menv GetInstalledOpts { getInstalledProfiling = profiling @@ -96,7 +96,7 @@ build setLocalFiles mbuildLk bopts = fixCodePage' $ do baseConfigOpts <- mkBaseConfigOpts bopts plan <- withLoadPackage menv $ \loadPackage -> - constructPlan mbp baseConfigOpts locals extraToBuild locallyRegistered loadPackage sourceMap installedMap + constructPlan mbp baseConfigOpts locals extraToBuild localDumpPkgs loadPackage sourceMap installedMap -- If our work to do is all local, let someone else have a turn with the snapshot. -- They won't damage what's already in there. @@ -114,7 +114,9 @@ build setLocalFiles mbuildLk bopts = fixCodePage' $ do if boptsDryrun bopts then printPlan plan else executePlan menv bopts baseConfigOpts locals - globallyRegistered + globalDumpPkgs + snapshotDumpPkgs + localDumpPkgs sourceMap installedMap plan diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index 94b1a77353..a4de022d91 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -11,6 +11,7 @@ module Stack.Build.ConstructPlan ( constructPlan ) where +import Control.Arrow ((&&&)) import Control.Exception.Lifted import Control.Monad import Control.Monad.Catch (MonadCatch) @@ -42,8 +43,8 @@ import Stack.Build.Installed import Stack.Build.Source import Stack.Types.Build import Stack.BuildPlan - import Stack.Package +import Stack.PackageDump import Stack.PackageIndex import Stack.Types @@ -126,12 +127,13 @@ constructPlan :: forall env m. -> BaseConfigOpts -> [LocalPackage] -> Set PackageName -- ^ additional packages that must be built - -> Map GhcPkgId PackageIdentifier -- ^ locally registered + -> [DumpPackage () ()] -- ^ locally registered -> (PackageName -> Version -> Map FlagName Bool -> IO Package) -- ^ load upstream package -> SourceMap -> InstalledMap -> m Plan -constructPlan mbp0 baseConfigOpts0 locals extraToBuild0 locallyRegistered loadPackage0 sourceMap installedMap = do +constructPlan mbp0 baseConfigOpts0 locals extraToBuild0 localDumpPkgs loadPackage0 sourceMap installedMap = do + let locallyRegistered = Map.fromList $ map (dpGhcPkgId &&& dpPackageIdent) localDumpPkgs menv <- getMinimalEnvOverride caches <- getPackageCaches menv let latest = Map.fromListWith max $ map toTuple $ Map.keys caches diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index a946ae7de4..a066ef5c95 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -206,7 +206,9 @@ data ExecuteEnv = ExecuteEnv , eeLocals :: ![LocalPackage] , eeSourceMap :: !SourceMap , eeGlobalDB :: !(Path Abs Dir) - , eeGlobalPackages :: ![DumpPackage () ()] + , eeGlobalDumpPkgs :: !(Map GhcPkgId (DumpPackage () ())) + , eeSnapshotDumpPkgs :: !(TVar (Map GhcPkgId (DumpPackage () ()))) + , eeLocalDumpPkgs :: !(TVar (Map GhcPkgId (DumpPackage () ()))) } -- | Get a compiled Setup exe @@ -279,10 +281,12 @@ withExecuteEnv :: M env m -> BaseConfigOpts -> [LocalPackage] -> [DumpPackage () ()] -- ^ global packages + -> [DumpPackage () ()] -- ^ snapshot packages + -> [DumpPackage () ()] -- ^ local packages -> SourceMap -> (ExecuteEnv -> m a) -> m a -withExecuteEnv menv bopts baseConfigOpts locals globals sourceMap inner = do +withExecuteEnv menv bopts baseConfigOpts locals globalPackages snapshotPackages localPackages sourceMap inner = do withCanonicalizedSystemTempDirectory stackProgName $ \tmpdir -> do configLock <- newMVar () installLock <- newMVar () @@ -292,6 +296,8 @@ withExecuteEnv menv bopts baseConfigOpts locals globals sourceMap inner = do setupExe <- getSetupExe setupHs tmpdir cabalPkgVer <- asks (envConfigCabalVersion . getEnvConfig) globalDB <- getGlobalDB menv =<< getWhichCompiler + snapshotPackagesTVar <- liftIO $ newTVarIO (toDumpPackagesByGhcPkgId snapshotPackages) + localPackagesTVar <- liftIO $ newTVarIO (toDumpPackagesByGhcPkgId localPackages) inner ExecuteEnv { eeEnvOverride = menv , eeBuildOpts = bopts @@ -312,8 +318,12 @@ withExecuteEnv menv bopts baseConfigOpts locals globals sourceMap inner = do , eeLocals = locals , eeSourceMap = sourceMap , eeGlobalDB = globalDB - , eeGlobalPackages = globals + , eeGlobalDumpPkgs = toDumpPackagesByGhcPkgId globalPackages + , eeSnapshotDumpPkgs = snapshotPackagesTVar + , eeLocalDumpPkgs = localPackagesTVar } + where + toDumpPackagesByGhcPkgId = Map.fromList . map (\dp -> (dpGhcPkgId dp, dp)) -- | Perform the actual plan executePlan :: M env m @@ -321,13 +331,15 @@ executePlan :: M env m -> BuildOpts -> BaseConfigOpts -> [LocalPackage] - -> [DumpPackage () ()] -- ^ globals + -> [DumpPackage () ()] -- ^ global packages + -> [DumpPackage () ()] -- ^ snapshot packages + -> [DumpPackage () ()] -- ^ local packages -> SourceMap -> InstalledMap -> Plan -> m () -executePlan menv bopts baseConfigOpts locals globals sourceMap installedMap plan = do - withExecuteEnv menv bopts baseConfigOpts locals globals sourceMap (executePlan' installedMap plan) +executePlan menv bopts baseConfigOpts locals globalPackages snapshotPackages localPackages sourceMap installedMap plan = do + withExecuteEnv menv bopts baseConfigOpts locals globalPackages snapshotPackages localPackages sourceMap (executePlan' installedMap plan) unless (Map.null $ planInstallExes plan) $ do snapBin <- ( bindirSuffix) `liftM` installationRootDeps @@ -419,9 +431,8 @@ executePlan' :: M env m -> Plan -> ExecuteEnv -> m () -executePlan' installedMap plan ee@ExecuteEnv {..} = do +executePlan' installedMap0 plan ee@ExecuteEnv {..} = do when (toCoverage $ boptsTestOpts eeBuildOpts) deleteHpcReports - wc <- getWhichCompiler cv <- asks $ envConfigCompilerVersion . getEnvConfig case Map.toList $ planUnregisterLocal plan of @@ -442,6 +453,9 @@ executePlan' installedMap plan ee@ExecuteEnv {..} = do ] unregisterGhcPkgId eeEnvOverride wc cv localDB id' ident + liftIO $ atomically $ modifyTVar' eeLocalDumpPkgs $ \initMap -> + foldl' (flip Map.delete) initMap $ Map.keys (planUnregisterLocal plan) + -- Yes, we're explicitly discarding result values, which in general would -- be bad. monad-unlift does this all properly at the type system level, -- but I don't want to pull it in for this one use case, when we know that @@ -489,11 +503,13 @@ executePlan' installedMap plan ee@ExecuteEnv {..} = do generateHpcMarkupIndex unless (null errs) $ throwM $ ExecutionFailure errs when (boptsHaddock eeBuildOpts) $ do + snapshotDumpPkgs <- liftIO (readTVarIO eeSnapshotDumpPkgs) + localDumpPkgs <- liftIO (readTVarIO eeLocalDumpPkgs) generateLocalHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeLocals - generateDepsHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeLocals - generateSnapHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeGlobalDB + generateDepsHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeGlobalDumpPkgs snapshotDumpPkgs localDumpPkgs eeLocals + generateSnapHaddockIndex eeEnvOverride wc eeBaseConfigOpts eeGlobalDumpPkgs snapshotDumpPkgs where - installedMap' = Map.difference installedMap + installedMap' = Map.difference installedMap0 $ Map.fromList $ map (\(ident, _) -> (packageIdentifierName ident, ())) $ Map.elems @@ -725,7 +741,7 @@ withSingleContext runInBase ActionContext {..} ExecuteEnv {..} task@Task {..} md let depsMinusCabal = map ghcPkgIdString $ Set.toList - $ addGlobalPackages deps eeGlobalPackages + $ addGlobalPackages deps (Map.elems eeGlobalDumpPkgs) in ( "-clear-package-db" : "-global-package-db" @@ -937,7 +953,7 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in -- Find the package in the database wc <- getWhichCompiler let pkgDbs = [bcoSnapDB eeBaseConfigOpts] - mpkgid <- findGhcPkgId eeEnvOverride wc pkgDbs pname + mpkgid <- loadInstalledPkg eeEnvOverride wc pkgDbs eeSnapshotDumpPkgs pname return $ Just $ case mpkgid of @@ -1022,14 +1038,17 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in cabal False ["copy"] cabal False ["register"] - let pkgDbs = + let (installedPkgDb, installedDumpPkgsTVar, dumpPkgsTVars) = case taskLocation task of - Snap -> [bcoSnapDB eeBaseConfigOpts] + Snap -> + ( bcoSnapDB eeBaseConfigOpts + , eeSnapshotDumpPkgs + , [eeSnapshotDumpPkgs] ) Local -> - [ bcoSnapDB eeBaseConfigOpts - , bcoLocalDB eeBaseConfigOpts - ] - mpkgid <- findGhcPkgId eeEnvOverride wc pkgDbs (packageName package) + ( bcoLocalDB eeBaseConfigOpts + , eeLocalDumpPkgs + , [eeSnapshotDumpPkgs, eeLocalDumpPkgs] ) + mpkgid <- loadInstalledPkg eeEnvOverride wc [installedPkgDb] installedDumpPkgsTVar (packageName package) let ident = PackageIdentifier (packageName package) (packageVersion package) mpkgid' <- case (packageHasLibrary package, mpkgid) of (False, _) -> assert (isNothing mpkgid) $ do @@ -1038,15 +1057,17 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in (True, Nothing) -> throwM $ Couldn'tFindPkgId $ packageName package (True, Just pkgid) -> return $ Library ident pkgid - when (doHaddock package && shouldHaddockDeps eeBuildOpts) $ - withMVar eeInstallLock $ \() -> - copyDepHaddocks - eeEnvOverride - wc - eeBaseConfigOpts - (pkgDbs ++ [eeGlobalDB]) - (PackageIdentifier (packageName package) (packageVersion package)) - Set.empty + case (doHaddock package && shouldHaddockDeps eeBuildOpts, mpkgid') of + (False, _) -> return () + (True, Executable _) -> return () + (True, Library _ ghcPkgId) -> + withMVar eeInstallLock $ \() -> do + dumpPkgs <- forM dumpPkgsTVars $ \tvar -> liftIO (readTVarIO tvar) + copyDepHaddocks + eeBaseConfigOpts + (reverse (eeGlobalDumpPkgs : dumpPkgs)) + ghcPkgId + Set.empty case taskLocation task of Snap -> writePrecompiledCache eeBaseConfigOpts taskProvides @@ -1057,6 +1078,15 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in return mpkgid' + loadInstalledPkg menv wc pkgDbs tvar name = do + dps <- ghcPkgDescribe name menv wc pkgDbs $ conduitDumpPackage =$ CL.consume + case dps of + [] -> return Nothing + [dp] -> do + liftIO $ atomically $ modifyTVar' tvar (Map.insert (dpGhcPkgId dp) dp) + return $ Just (dpGhcPkgId dp) + _ -> error "singleBuild: invariant violated: multiple results when describing installed package" + -- | Determine if all of the dependencies given are installed depsPresent :: InstalledMap -> Map PackageName VersionRange -> Bool depsPresent installedMap deps = all diff --git a/src/Stack/Build/Haddock.hs b/src/Stack/Build/Haddock.hs index 937cd87852..e41bca5df9 100644 --- a/src/Stack/Build/Haddock.hs +++ b/src/Stack/Build/Haddock.hs @@ -3,6 +3,7 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} -- | Generate haddocks @@ -21,10 +22,12 @@ import Control.Monad.Catch (MonadCatch) import Control.Monad.IO.Class import Control.Monad.Logger import Control.Monad.Trans.Resource -import Control.Monad.Writer import Data.Function import Data.List +import Data.List.Extra (nubOrd) import Data.Maybe +import Data.Map.Strict (Map) +import qualified Data.Map.Strict as Map import Data.Set (Set) import qualified Data.Set as Set import Data.Text (Text) @@ -34,10 +37,10 @@ import Path.IO import Prelude import Safe (maximumMay) import Stack.Types.Build -import Stack.GhcPkg -import Stack.Package +import Stack.PackageDump import Stack.Types -import System.Directory (getModificationTime) +import System.Directory (getModificationTime, canonicalizePath, + doesDirectoryExist) import qualified System.FilePath as FP import System.IO.Error (isDoesNotExistError) import System.Process.Read @@ -59,34 +62,45 @@ shouldHaddockDeps bopts = fromMaybe (boptsHaddock bopts) (boptsHaddockDeps bopts -- reliably supported on Windows, and (2) the filesystem containing dependencies' docs may not be -- available where viewing the docs (e.g. if building in a Docker container). copyDepHaddocks :: (MonadIO m, MonadLogger m, MonadThrow m, MonadCatch m, MonadBaseControl IO m) - => EnvOverride - -> WhichCompiler - -> BaseConfigOpts - -> [Path Abs Dir] - -> PackageIdentifier + => BaseConfigOpts + -> [Map GhcPkgId (DumpPackage () ())] + -> GhcPkgId -> Set (Path Abs Dir) -> m () -copyDepHaddocks envOverride wc bco pkgDbs pkgId extraDestDirs = do - mpkgHtmlDir <- findGhcPkgHaddockHtml envOverride wc pkgDbs $ packageIdentifierString pkgId - case mpkgHtmlDir of +copyDepHaddocks bco dumpPkgs ghcPkgId extraDestDirs = do + let mdp = lookupDumpPackage ghcPkgId dumpPkgs + case mdp of Nothing -> return () - Just (_pkgId, pkgHtmlDir) -> do - depGhcIds <- findGhcPkgDepends envOverride wc pkgDbs $ packageIdentifierString pkgId - forM_ depGhcIds $ copyDepWhenNeeded pkgHtmlDir + Just dp -> + forM_ (dpDepends dp) $ \depDP -> + case dpHaddockHtml dp of + Nothing -> return () + Just pkgHtmlFP -> do + pkgHtmlDir <- parseAbsDir pkgHtmlFP + copyDepWhenNeeded pkgHtmlDir depDP where - copyDepWhenNeeded pkgHtmlDir depGhcId = do - mDepOrigDir <- findGhcPkgHaddockHtml envOverride wc pkgDbs $ ghcPkgIdString depGhcId - case mDepOrigDir of + copyDepWhenNeeded pkgHtmlDir depGhcPkgId = do + let mDepDP = lookupDumpPackage depGhcPkgId dumpPkgs + case mDepDP of Nothing -> return () - Just (depId, depOrigDir) -> do - let extraDestDirs' = - -- Parent test ensures we don't try to copy docs to global locations - if bcoSnapInstallRoot bco `isParentOf` pkgHtmlDir || - bcoLocalInstallRoot bco `isParentOf` pkgHtmlDir - then Set.insert (parent pkgHtmlDir) extraDestDirs - else extraDestDirs - copyWhenNeeded extraDestDirs' depId depOrigDir - copyWhenNeeded destDirs depId depOrigDir = do + Just depDP -> + case dpHaddockHtml depDP of + Nothing -> return () + Just depOrigFP0 -> do + let extraDestDirs' = + -- Parent test ensures we don't try to copy docs to global locations + if bcoSnapInstallRoot bco `isParentOf` pkgHtmlDir || + bcoLocalInstallRoot bco `isParentOf` pkgHtmlDir + then Set.insert (parent pkgHtmlDir) extraDestDirs + else extraDestDirs + depOrigFP <- liftIO $ do + exists <- doesDirectoryExist depOrigFP0 + if exists + then canonicalizePath depOrigFP0 + else return depOrigFP0 + depOrigDir <- parseAbsDir depOrigFP + copyWhenNeeded extraDestDirs' (dpPackageIdent depDP) (dpGhcPkgId depDP) depOrigDir + copyWhenNeeded destDirs depId depGhcPkgId depOrigDir = do depRelDir <- parseRelDir (packageIdentifierString depId) copied <- forM (Set.toList destDirs) $ \destDir -> do let depCopyDir = destDir depRelDir @@ -97,7 +111,7 @@ copyDepHaddocks envOverride wc bco pkgDbs pkgId extraDestDirs = do when needCopy $ doCopy depOrigDir depCopyDir return needCopy when (or copied) $ - copyDepHaddocks envOverride wc bco pkgDbs depId destDirs + copyDepHaddocks bco dumpPkgs depGhcPkgId destDirs getNeedCopy depOrigDir depCopyDir = do let depOrigIndex = haddockIndexFile depOrigDir depCopyIndex = haddockIndexFile depCopyDir @@ -136,36 +150,66 @@ generateLocalHaddockIndex envOverride wc bco locals = do -- | Generate Haddock index and contents for local packages and their dependencies. generateDepsHaddockIndex :: (MonadIO m, MonadCatch m, MonadThrow m, MonadLogger m, MonadBaseControl IO m) - => EnvOverride -> WhichCompiler -> BaseConfigOpts -> [LocalPackage] -> m () -generateDepsHaddockIndex envOverride wc bco locals = do - depSets <- - mapM - (\LocalPackage{lpPackage = Package{..}} -> - findTransitiveGhcPkgDepends - envOverride - wc - [bcoSnapDB bco, bcoLocalDB bco] - (PackageIdentifier packageName packageVersion)) - locals + => EnvOverride + -> WhichCompiler + -> BaseConfigOpts + -> Map GhcPkgId (DumpPackage () ()) + -> Map GhcPkgId (DumpPackage () ()) + -> Map GhcPkgId (DumpPackage () ()) + -> [LocalPackage] + -> m () +generateDepsHaddockIndex envOverride wc bco globalDumpPkgs snapshotDumpPkgs localDumpPkgs locals = do + let depGhcPkgIds = + map + (\LocalPackage{lpPackage = Package{..}} -> + let pkgId = PackageIdentifier packageName packageVersion + in case find + (\dp -> + dpPackageIdent dp == pkgId) + (Map.elems localDumpPkgs) of + Nothing -> Set.empty + Just dp -> findTransitiveDepends (dpGhcPkgId dp)) + locals + depDumpPkgs = + map + (\ghcPkgId -> + lookupDumpPackage ghcPkgId allDumpPkgs) + (Set.toList $ Set.unions depGhcPkgIds) generateHaddockIndex "local packages and dependencies" envOverride wc - (Set.toList (Set.unions depSets)) + (nubOrd $ map dpPackageIdent $ catMaybes depDumpPkgs) ".." (localDocDir bco $(mkRelDir "all")) + where + findTransitiveDepends ghcPkgId = + case lookupDumpPackage ghcPkgId allDumpPkgs of + Nothing -> Set.singleton ghcPkgId + Just pkgDP -> + Set.unions + (Set.singleton ghcPkgId : + map findTransitiveDepends (dpDepends pkgDP)) + allDumpPkgs = [localDumpPkgs, snapshotDumpPkgs, globalDumpPkgs] -- | Generate Haddock index and contents for all snapshot packages. generateSnapHaddockIndex :: (MonadIO m, MonadCatch m, MonadThrow m, MonadLogger m, MonadBaseControl IO m) - => EnvOverride -> WhichCompiler -> BaseConfigOpts -> Path Abs Dir -> m () -generateSnapHaddockIndex envOverride wc bco globalDB = do - pkgIds <- listGhcPkgDbs envOverride wc [globalDB, bcoSnapDB bco] + => EnvOverride + -> WhichCompiler + -> BaseConfigOpts + -> Map GhcPkgId (DumpPackage () ()) + -> Map GhcPkgId (DumpPackage () ()) + -> m () +generateSnapHaddockIndex envOverride wc bco globalDumpPkgs snapshotDumpPkgs = generateHaddockIndex "snapshot packages" envOverride wc - pkgIds + (nubOrd $ + map + dpPackageIdent + (Map.elems globalDumpPkgs ++ Map.elems snapshotDumpPkgs)) "." (snapDocDir bco) @@ -197,8 +241,8 @@ generateHaddockIndex descr envOverride wc packageIDs docRelDir destDir = do when needUpdate $ do $logInfo - ("Updating Haddock index for " <> descr <> " in\n" <> - T.pack (toFilePath (haddockIndexFile destDir))) + (T.concat ["Updating Haddock index for ", descr, " in\n", + T.pack (toFilePath (haddockIndexFile destDir))]) readProcessNull (Just destDir) envOverride @@ -226,6 +270,13 @@ generateHaddockIndex descr envOverride wc packageIDs docRelDir destDir = do , interfaceRelFile]] , interfaceModTime) +-- | Find first DumpPackage matching the GhcPkgId +lookupDumpPackage :: GhcPkgId + -> [Map GhcPkgId (DumpPackage () ())] + -> Maybe (DumpPackage () ()) +lookupDumpPackage ghcPkgId dumpPkgs = + listToMaybe $ catMaybes $ map (Map.lookup ghcPkgId) dumpPkgs + -- | Path of haddock index file. haddockIndexFile :: Path Abs Dir -> Path Abs File haddockIndexFile destDir = destDir $(mkRelFile "index.html") diff --git a/src/Stack/Build/Installed.hs b/src/Stack/Build/Installed.hs index b7dff7528c..8a71d6494a 100644 --- a/src/Stack/Build/Installed.hs +++ b/src/Stack/Build/Installed.hs @@ -12,7 +12,6 @@ module Stack.Build.Installed ) where import Control.Applicative -import Control.Arrow ((&&&)) import Control.Monad import Control.Monad.Catch (MonadCatch, MonadMask) import Control.Monad.IO.Class @@ -59,7 +58,8 @@ getInstalled :: (M env m, PackageInstallInfo pii) -> Map PackageName pii -- ^ does not contain any installed information -> m ( InstalledMap , [DumpPackage () ()] -- globally installed - , Map GhcPkgId PackageIdentifier -- locally installed + , [DumpPackage () ()] -- snapshot installed + , [DumpPackage () ()] -- locally installed ) getInstalled menv opts sourceMap = do snapDBPath <- packageDatabaseDeps @@ -75,14 +75,14 @@ getInstalled menv opts sourceMap = do let loadDatabase' = loadDatabase menv opts mcache sourceMap - (installedLibs0, globalInstalled) <- loadDatabase' Nothing [] + (installedLibs0, globalDumpPkgs) <- loadDatabase' Nothing [] (installedLibs1, _extraInstalled) <- (foldM (\lhs' pkgdb -> do lhs'' <- loadDatabase' (Just (ExtraGlobal, pkgdb)) (fst lhs') - return lhs'') (installedLibs0, globalInstalled) extraDBPaths) - (installedLibs2, _snapInstalled) <- + return lhs'') (installedLibs0, globalDumpPkgs) extraDBPaths) + (installedLibs2, snapshotDumpPkgs) <- loadDatabase' (Just (InstalledTo Snap, snapDBPath)) installedLibs1 - (installedLibs3, localInstalled) <- + (installedLibs3, localDumpPkgs) <- loadDatabase' (Just (InstalledTo Local, localDBPath)) installedLibs2 let installedLibs = M.fromList $ map lhPair installedLibs3 @@ -113,8 +113,9 @@ getInstalled menv opts sourceMap = do ] return ( installedMap - , globalInstalled - , Map.fromList $ map (dpGhcPkgId &&& dpPackageIdent) localInstalled + , globalDumpPkgs + , snapshotDumpPkgs + , localDumpPkgs ) -- | Outputs both the modified InstalledMap and the Set of all installed packages in this database diff --git a/src/Stack/Dot.hs b/src/Stack/Dot.hs index d4f927f025..6cd1c14b3d 100644 --- a/src/Stack/Dot.hs +++ b/src/Stack/Dot.hs @@ -92,7 +92,7 @@ createDependencyGraph dotOpts = do (_,_,locals,_,sourceMap) <- loadSourceMap NeedTargets defaultBuildOpts let graph = Map.fromList (localDependencies dotOpts locals) menv <- getMinimalEnvOverride - installedMap <- fmap snd . fst3 <$> getInstalled menv + installedMap <- fmap snd . fst4 <$> getInstalled menv (GetInstalledOpts False False) sourceMap withLoadPackage menv (\loader -> do @@ -105,8 +105,8 @@ createDependencyGraph dotOpts = do fmap3 :: Functor f => (d -> e) -> (a -> b -> c -> f d) -> a -> b -> c -> f e fmap3 f g a b c = f <$> g a b c - fst3 :: (a,b,c) -> a - fst3 (x,_,_) = x + fst4 :: (a,b,c,d) -> a + fst4 (x,_,_,_) = x listDependencies :: (HasEnvConfig env ,HasHttpManager env diff --git a/src/Stack/GhcPkg.hs b/src/Stack/GhcPkg.hs index dd1e659cc8..7b0b81bf3d 100644 --- a/src/Stack/GhcPkg.hs +++ b/src/Stack/GhcPkg.hs @@ -10,22 +10,16 @@ -- | Functions for the GHC package database. module Stack.GhcPkg - (findGhcPkgId - ,getGlobalDB + (getGlobalDB ,EnvOverride ,envHelper ,createDatabase ,unregisterGhcPkgId ,getCabalPkgVer - ,findGhcPkgHaddockHtml - ,findGhcPkgDepends - ,findTransitiveGhcPkgDepends - ,listGhcPkgDbs ,ghcPkgExeName ,mkGhcPackagePath) where -import Control.Applicative import Control.Monad import Control.Monad.Catch import Control.Monad.IO.Class @@ -34,10 +28,7 @@ import Control.Monad.Trans.Control import qualified Data.ByteString.Char8 as S8 import Data.Either import Data.List -import qualified Data.Map as Map import Data.Maybe -import Data.Set (Set) -import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as T @@ -47,7 +38,7 @@ import Path.IO (dirExists, createTree) import Prelude hiding (FilePath) import Stack.Constants import Stack.Types -import System.Directory (canonicalizePath, doesDirectoryExist) +import System.Directory (canonicalizePath) import System.FilePath (searchPathSeparator) import System.Process.Read @@ -134,19 +125,6 @@ findGhcPkgField menv wc pkgDbs name field = do where stripCR t = fromMaybe t (T.stripSuffix "\r" t) --- | Get the id of the package e.g. @foo-0.0.0-9c293923c0685761dcff6f8c3ad8f8ec@. -findGhcPkgId :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride - -> WhichCompiler - -> [Path Abs Dir] -- ^ package databases - -> PackageName - -> m (Maybe GhcPkgId) -findGhcPkgId menv wc pkgDbs name = do - mpid <- findGhcPkgField menv wc pkgDbs (packageNameString name) "id" - case mpid of - Just !pid -> return (parseGhcPkgId (T.encodeUtf8 pid)) - _ -> return Nothing - -- | Get the version of the package findGhcPkgVersion :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) => EnvOverride @@ -160,76 +138,6 @@ findGhcPkgVersion menv wc pkgDbs name = do Just !v -> return (parseVersion (T.encodeUtf8 v)) _ -> return Nothing --- | Get the Haddock HTML documentation path of the package. -findGhcPkgHaddockHtml :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride - -> WhichCompiler - -> [Path Abs Dir] -- ^ package databases - -> String -- ^ PackageIdentifier or GhcPkgId - -> m (Maybe (PackageIdentifier, Path Abs Dir)) -findGhcPkgHaddockHtml menv wc pkgDbs ghcPkgId = do - mpath <- findGhcPkgField menv wc pkgDbs ghcPkgId "haddock-html" - mid <- findGhcPkgField menv wc pkgDbs ghcPkgId "id" - mversion <- findGhcPkgField menv wc pkgDbs ghcPkgId "version" - let mpkgId = PackageIdentifier - <$> (mid >>= parsePackageName . T.encodeUtf8) - <*> (mversion >>= parseVersion . T.encodeUtf8) - case (,) <$> mpath <*> mpkgId of - Just (path0, pkgId) -> do - let path = T.unpack path0 - exists <- liftIO $ doesDirectoryExist path - path' <- if exists - then liftIO $ canonicalizePath path - else return path - - return $ fmap (pkgId,) (parseAbsDir path') - _ -> return Nothing - --- | Finds dependencies of package, and all their dependencies, etc. -findTransitiveGhcPkgDepends - :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride - -> WhichCompiler - -> [Path Abs Dir] -- ^ package databases - -> PackageIdentifier - -> m (Set PackageIdentifier) -findTransitiveGhcPkgDepends menv wc pkgDbs pkgId0 = - liftM (Set.fromList . Map.elems) - (go (packageIdentifierString pkgId0) Map.empty) - where - go pkgId res = do - deps <- findGhcPkgDepends menv wc pkgDbs pkgId - loop deps res - loop [] res = return res - loop (dep:deps) res = do - if Map.member dep res - then loop deps res - else do - let pkgId = ghcPkgIdString dep - mname <- findGhcPkgField menv wc pkgDbs pkgId "name" - mversion <- findGhcPkgField menv wc pkgDbs pkgId "version" - let mident = do - name <- mname >>= parsePackageName . T.encodeUtf8 - version <- mversion >>= parseVersion . T.encodeUtf8 - Just $ PackageIdentifier name version - res' = maybe id (Map.insert dep) mident res - res'' <- go pkgId res' - -- FIXME is the Map.union actually necessary? - loop deps (Map.union res res'') - --- | Get the dependencies of the package. -findGhcPkgDepends :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride - -> WhichCompiler - -> [Path Abs Dir] -- ^ package databases - -> String -- ^ package identifier or GhcPkgId - -> m [GhcPkgId] -findGhcPkgDepends menv wc pkgDbs pkgId = do - mdeps <- findGhcPkgField menv wc pkgDbs pkgId "depends" - case mdeps of - Just !deps -> return (mapMaybe (parseGhcPkgId . T.encodeUtf8) (T.words deps)) - _ -> return [] - unregisterGhcPkgId :: (MonadIO m, MonadLogger m, MonadThrow m, MonadCatch m, MonadBaseControl IO m) => EnvOverride -> WhichCompiler @@ -262,21 +170,6 @@ getCabalPkgVer menv wc = cabalPackageName >>= maybe (throwM $ Couldn'tFindPkgId cabalPackageName) return -listGhcPkgDbs - :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) - => EnvOverride -> WhichCompiler -> [Path Abs Dir] -> m [PackageIdentifier] -listGhcPkgDbs menv wc pkgDbs = do - result <- - ghcPkg - menv - wc - pkgDbs - ["list", "--simple-output"] - return $ - case result of - Left{} -> [] - Right lbs -> mapMaybe parsePackageIdentifier (S8.words lbs) - -- | Get the value for GHC_PACKAGE_PATH mkGhcPackagePath :: Bool -> Path Abs Dir -> Path Abs Dir -> Path Abs Dir -> Text mkGhcPackagePath locals localdb deps globaldb = diff --git a/src/Stack/Ghci.hs b/src/Stack/Ghci.hs index 4c56cd8bc2..88bad0896e 100644 --- a/src/Stack/Ghci.hs +++ b/src/Stack/Ghci.hs @@ -179,7 +179,7 @@ ghciSetup mainIs stringTargets = do econfig <- asks getEnvConfig (realTargets,_,_,_,sourceMap) <- loadSourceMap AllowNoTargets bopts menv <- getMinimalEnvOverride - (installedMap, _, _) <- getInstalled + (installedMap, _, _, _) <- getInstalled menv GetInstalledOpts { getInstalledProfiling = False diff --git a/src/Stack/PackageDump.hs b/src/Stack/PackageDump.hs index 0cceceb4d7..325281897c 100644 --- a/src/Stack/PackageDump.hs +++ b/src/Stack/PackageDump.hs @@ -13,6 +13,7 @@ module Stack.PackageDump , DumpPackage (..) , conduitDumpPackage , ghcPkgDump + , ghcPkgDescribe , InstalledCache , InstalledCacheEntry (..) , newInstalledCache @@ -45,7 +46,7 @@ import Data.Either (partitionEithers) import Data.IORef import Data.Map (Map) import qualified Data.Map as Map -import Data.Maybe (catMaybes) +import Data.Maybe (catMaybes, listToMaybe) import qualified Data.Set as Set import qualified Data.Text.Encoding as T import Data.Typeable (Typeable) @@ -83,7 +84,29 @@ ghcPkgDump -> [Path Abs Dir] -- ^ if empty, use global -> Sink ByteString IO a -> m a -ghcPkgDump menv wc mpkgDbs sink = do +ghcPkgDump = ghcPkgCmdArgs ["dump"] + +-- | Call ghc-pkg describe with appropriate flags and stream to the given @Sink@, for a single database +ghcPkgDescribe + :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) + => PackageName + -> EnvOverride + -> WhichCompiler + -> [Path Abs Dir] -- ^ if empty, use global + -> Sink ByteString IO a + -> m a +ghcPkgDescribe pkgName = ghcPkgCmdArgs ["describe", "--simple-output", packageNameString pkgName] + +-- | Call ghc-pkg and stream to the given @Sink@, for a single database +ghcPkgCmdArgs + :: (MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadCatch m, MonadThrow m) + => [String] + -> EnvOverride + -> WhichCompiler + -> [Path Abs Dir] -- ^ if empty, use global + -> Sink ByteString IO a + -> m a +ghcPkgCmdArgs cmd menv wc mpkgDbs sink = do case reverse mpkgDbs of (pkgDb:_) -> (createDatabase menv wc) pkgDb -- TODO maybe use some retry logic instead? _ -> return () @@ -94,7 +117,8 @@ ghcPkgDump menv wc mpkgDbs sink = do [ case mpkgDbs of [] -> ["--global", "--no-user-package-db"] _ -> ["--user", "--no-user-package-db"] ++ concatMap (\pkgDb -> ["--package-db", toFilePath pkgDb]) mpkgDbs - , ["dump", "--expand-pkgroot"] + , cmd + , ["--expand-pkgroot"] ] -- | Create a new, empty @InstalledCache@ @@ -247,6 +271,7 @@ data DumpPackage profiling haddock = DumpPackage , dpHasExposedModules :: !Bool , dpDepends :: ![GhcPkgId] , dpHaddockInterfaces :: ![FilePath] + , dpHaddockHtml :: !(Maybe FilePath) , dpProfiling :: !profiling , dpHaddock :: !haddock , dpIsExposed :: !Bool @@ -321,6 +346,7 @@ conduitDumpPackage = (=$= CL.catMaybes) $ eachSection $ do val = parseM key libDirPaths <- parseQuoted libDirKey haddockInterfaces <- parseQuoted "haddock-interfaces" + haddockHtml <- parseQuoted "haddock-html" return $ Just DumpPackage { dpGhcPkgId = ghcPkgId @@ -330,6 +356,7 @@ conduitDumpPackage = (=$= CL.catMaybes) $ eachSection $ do , dpHasExposedModules = not (null libraries || null exposedModules) , dpDepends = catMaybes (depends :: [Maybe GhcPkgId]) , dpHaddockInterfaces = haddockInterfaces + , dpHaddockHtml = listToMaybe haddockHtml , dpProfiling = () , dpHaddock = () , dpIsExposed = exposed == ["True"] diff --git a/src/Stack/SDist.hs b/src/Stack/SDist.hs index 22ed82707f..fee3859bdf 100644 --- a/src/Stack/SDist.hs +++ b/src/Stack/SDist.hs @@ -103,7 +103,7 @@ getCabalLbs pvpBounds fp = do (_warnings, gpd) <- readPackageUnresolvedBS Nothing bs (_, _, _, _, sourceMap) <- loadSourceMap AllowNoTargets defaultBuildOpts menv <- getMinimalEnvOverride - (installedMap, _, _) <- getInstalled menv GetInstalledOpts + (installedMap, _, _, _) <- getInstalled menv GetInstalledOpts { getInstalledProfiling = False , getInstalledHaddock = False } @@ -195,7 +195,7 @@ getSDistFileList lp = (_, _mbp, locals, _extraToBuild, sourceMap) <- loadSourceMap NeedTargets bopts runInBase <- liftBaseWith $ \run -> return (void . run) withExecuteEnv menv bopts baseConfigOpts locals - [] -- provide empty list of globals. This is a hack around custom Setup.hs files + [] [] [] -- provide empty list of globals. This is a hack around custom Setup.hs files sourceMap $ \ee -> do withSingleContext runInBase ac ee task Nothing (Just "sdist") $ \_package cabalfp _pkgDir cabal _announce _console _mlogFile -> do let outFile = toFilePath tmpdir FP. "source-files-list" diff --git a/src/test/Stack/PackageDumpSpec.hs b/src/test/Stack/PackageDumpSpec.hs index ba13b416f5..07640ef982 100644 --- a/src/test/Stack/PackageDumpSpec.hs +++ b/src/test/Stack/PackageDumpSpec.hs @@ -80,6 +80,7 @@ spec = do , dpLibraries = ["HShaskell2010-1.1.2.0"] , dpHasExposedModules = True , dpHaddockInterfaces = ["/opt/ghc/7.8.4/share/doc/ghc/html/libraries/haskell2010-1.1.2.0/haskell2010.haddock"] + , dpHaddockHtml = Just "/opt/ghc/7.8.4/share/doc/ghc/html/libraries/haskell2010-1.1.2.0" , dpProfiling = () , dpHaddock = () , dpIsExposed = False @@ -113,6 +114,7 @@ spec = do , dpPackageIdent = pkgIdent , dpLibDirs = ["/opt/ghc/7.10.1/lib/ghc-7.10.1/ghc_EMlWrQ42XY0BNVbSrKixqY"] , dpHaddockInterfaces = ["/opt/ghc/7.10.1/share/doc/ghc/html/libraries/ghc-7.10.1/ghc.haddock"] + , dpHaddockHtml = Just "/opt/ghc/7.10.1/share/doc/ghc/html/libraries/ghc-7.10.1" , dpDepends = depends , dpLibraries = ["HSghc-7.10.1-EMlWrQ42XY0BNVbSrKixqY"] , dpHasExposedModules = True @@ -146,6 +148,7 @@ spec = do , "/usr/local/lib/" , "C:/Program Files/Example/"] , dpHaddockInterfaces = ["/Users/alexbiehl/.stack/snapshots/x86_64-osx/lts-2.13/7.8.4/doc/html/hmatrix.haddock"] + , dpHaddockHtml = Just "/Users/alexbiehl/.stack/snapshots/x86_64-osx/lts-2.13/7.8.4/doc/html" , dpDepends = depends , dpLibraries = ["HShmatrix-0.16.1.5"] , dpHasExposedModules = True diff --git a/stack-7.8.yaml b/stack-7.8.yaml index a72113f808..a07156ea01 100644 --- a/stack-7.8.yaml +++ b/stack-7.8.yaml @@ -11,3 +11,4 @@ extra-deps: - ignore-0.1.1.0 - binary-tagged-0.1.1.0 - fsnotify-0.2.1 +- ansi-terminal-0.6.2.3 From 33462aba13f85a3d5c1690c6ee0bb3dd4af6b616 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sat, 24 Oct 2015 15:10:03 -0700 Subject: [PATCH 089/106] Update changelog --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index c97c2a747d..be488c039e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -16,6 +16,8 @@ Other enhancements: Bug fixes: +* Haddocks not copied for dependencies [#1105](https://github.com/commercialhaskell/stack/issues/1105) + ## v0.1.6.0 Major changes: From bc3c41a691108a160d40ca5812e53026c266dc86 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Sun, 25 Oct 2015 07:20:15 +0000 Subject: [PATCH 090/106] watched command: show files, not directories --- src/Stack/FileWatch.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Stack/FileWatch.hs b/src/Stack/FileWatch.hs index 4ff071d084..9cac71d705 100644 --- a/src/Stack/FileWatch.hs +++ b/src/Stack/FileWatch.hs @@ -96,11 +96,11 @@ fileWatchConf cfg inner = withManagerConf cfg $ \manager -> do putStrLn "help: display this help" putStrLn "quit: exit" putStrLn "build: force a rebuild" - putStrLn "watched: display watched directories" + putStrLn "watched: display watched files" "build" -> atomically $ writeTVar dirtyVar True "watched" -> do - watch <- readTVarIO watchVar - mapM_ (putStrLn . toFilePath) (Map.keys watch) + watch <- readTVarIO allFiles + mapM_ putStrLn (Set.toList watch) "" -> atomically $ writeTVar dirtyVar True _ -> putStrLn $ concat [ "Unknown command: " From 4617847506ef78b39d04bac68a7527493a2f9ece Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Sun, 25 Oct 2015 07:29:35 +0000 Subject: [PATCH 091/106] Rebuild when cabal file is changed Pinging @borsboom @mgsloan. I thought I remembered seeing an issue about this, but I couldn't find it. If you know which issue that is, please feel free to close it. --- ChangeLog.md | 1 + src/Stack/Package.hs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index be488c039e..8cabeb2b0d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,6 +17,7 @@ Other enhancements: Bug fixes: * Haddocks not copied for dependencies [#1105](https://github.com/commercialhaskell/stack/issues/1105) +* Rebuild when cabal file is changed ## v0.1.6.0 diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index a4e3f241e4..40fdaee73c 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -213,11 +213,11 @@ resolvePackage packageConfig gpkg = pkgFiles = GetPackageFiles $ \cabalfp -> do distDir <- distDirFromDir (parent cabalfp) - (componentModules,componentFiles,cabalFiles,warnings) <- + (componentModules,componentFiles,dataFiles',warnings) <- runReaderT (packageDescModulesAndFiles pkg) (cabalfp, buildDir distDir) - return (componentModules, componentFiles, cabalFiles, warnings) + return (componentModules, componentFiles, S.insert cabalfp dataFiles', warnings) pkgId = package (packageDescription gpkg) name = fromCabalPackageName (pkgName pkgId) pkg = resolvePackageDescription packageConfig gpkg From b6c5233dd4cf40a2cfd9191603a81e1618660f51 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sun, 25 Oct 2015 07:21:42 -0700 Subject: [PATCH 092/106] Fix help for default true bool flag's enable hint --- src/Options/Applicative/Builder/Extra.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Options/Applicative/Builder/Extra.hs b/src/Options/Applicative/Builder/Extra.hs index e3dd96e5ac..c58880af2b 100644 --- a/src/Options/Applicative/Builder/Extra.hs +++ b/src/Options/Applicative/Builder/Extra.hs @@ -70,7 +70,7 @@ enableDisableFlagsNoDefault' enabledValue disabledValue maybeHideValue name help help (concat $ concat [ ["Disable ", helpSuffix] - , [" (--no-" ++ name ++ " to enable)" | hideEnabled]]) <> + , [" (--" ++ name ++ " to enable)" | hideEnabled]]) <> mods) <|> flag' disabledValue From 5cc457e13fcedf326a7bb48a87ed4637ab873980 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Sun, 25 Oct 2015 19:18:52 +0000 Subject: [PATCH 093/106] Don't fail when registering/looking up library for executable-only packages #1232 --- src/Stack/Build/Cache.hs | 6 +++--- src/Stack/Build/Execute.hs | 32 +++++++++++++++++++------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Stack/Build/Cache.hs b/src/Stack/Build/Cache.hs index 14b2be2f57..2a38ee60ab 100644 --- a/src/Stack/Build/Cache.hs +++ b/src/Stack/Build/Cache.hs @@ -342,7 +342,7 @@ writePrecompiledCache :: (MonadThrow m, MonadReader env m, HasEnvConfig env, Mon -> PackageIdentifier -> ConfigureOpts -> Set GhcPkgId -- ^ dependencies - -> Maybe GhcPkgId -- ^ library + -> Installed -- ^ library -> Set Text -- ^ executables -> m () writePrecompiledCache baseConfigOpts pkgident copts depIDs mghcPkgId exes = do @@ -350,8 +350,8 @@ writePrecompiledCache baseConfigOpts pkgident copts depIDs mghcPkgId exes = do createTree $ parent file mlibpath <- case mghcPkgId of - Nothing -> return Nothing - Just ipid -> liftM Just $ do + Executable _ -> return Nothing + Library _ ipid -> liftM Just $ do ipid' <- parseRelFile $ ghcPkgIdString ipid ++ ".conf" return $ toFilePath $ bcoSnapDB baseConfigOpts ipid' exes' <- forM (Set.toList exes) $ \exe -> do diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index a066ef5c95..4498113e76 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -953,12 +953,16 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in -- Find the package in the database wc <- getWhichCompiler let pkgDbs = [bcoSnapDB eeBaseConfigOpts] - mpkgid <- loadInstalledPkg eeEnvOverride wc pkgDbs eeSnapshotDumpPkgs pname - return $ Just $ - case mpkgid of - Nothing -> Executable taskProvides - Just pkgid -> Library taskProvides pkgid + case mlib of + Nothing -> return $ Just $ Executable taskProvides + Just _ -> do + mpkgid <- loadInstalledPkg eeEnvOverride wc pkgDbs eeSnapshotDumpPkgs pname + + return $ Just $ + case mpkgid of + Nothing -> assert False $ Executable taskProvides + Just pkgid -> Library taskProvides pkgid where bindir = toFilePath $ bcoSnapInstallRoot eeBaseConfigOpts bindirSuffix @@ -1036,7 +1040,7 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in withMVar eeInstallLock $ \() -> do announce "copy/register" cabal False ["copy"] - cabal False ["register"] + when (packageHasLibrary package) $ cabal False ["register"] let (installedPkgDb, installedDumpPkgsTVar, dumpPkgsTVars) = case taskLocation task of @@ -1048,16 +1052,18 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in ( bcoLocalDB eeBaseConfigOpts , eeLocalDumpPkgs , [eeSnapshotDumpPkgs, eeLocalDumpPkgs] ) - mpkgid <- loadInstalledPkg eeEnvOverride wc [installedPkgDb] installedDumpPkgsTVar (packageName package) let ident = PackageIdentifier (packageName package) (packageVersion package) - mpkgid' <- case (packageHasLibrary package, mpkgid) of - (False, _) -> assert (isNothing mpkgid) $ do + mpkgid <- if packageHasLibrary package + then do + mpkgid <- loadInstalledPkg eeEnvOverride wc [installedPkgDb] installedDumpPkgsTVar (packageName package) + case mpkgid of + Nothing -> throwM $ Couldn'tFindPkgId $ packageName package + Just pkgid -> return $ Library ident pkgid + else do markExeInstalled (taskLocation task) taskProvides -- TODO unify somehow with writeFlagCache? return $ Executable ident - (True, Nothing) -> throwM $ Couldn'tFindPkgId $ packageName package - (True, Just pkgid) -> return $ Library ident pkgid - case (doHaddock package && shouldHaddockDeps eeBuildOpts, mpkgid') of + case (doHaddock package && shouldHaddockDeps eeBuildOpts, mpkgid) of (False, _) -> return () (True, Executable _) -> return () (True, Library _ ghcPkgId) -> @@ -1076,7 +1082,7 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in mpkgid (packageExes package) Local -> return () - return mpkgid' + return mpkgid loadInstalledPkg menv wc pkgDbs tvar name = do dps <- ghcPkgDescribe name menv wc pkgDbs $ conduitDumpPackage =$ CL.consume From 7264ef6d99f19091f6521722aa620f4b59dba9e3 Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Sun, 25 Oct 2015 13:19:13 -0700 Subject: [PATCH 094/106] Fix: unlisted files in tests and benchmarks trigger extraneous second build (fixes #838) --- src/Stack/Build/Execute.hs | 34 ++++++++++++++++++++-------------- src/Stack/Build/Source.hs | 4 ++-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 4498113e76..01808a5d88 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -1004,20 +1004,7 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in Nothing -> packageExes package ] TTUpstream _ _ -> ["build"]) ++ extraOpts - - case taskType of - TTLocal lp -> do - (addBuildCache,warnings) <- - addUnlistedToBuildCache - preBuildTime - (lpPackage lp) - (lpCabalFile lp) - (lpNewBuildCache lp) - mapM_ ($logWarn . ("Warning: " <>) . T.pack . show) warnings - unless (null addBuildCache) $ - writeBuildCache pkgDir $ - Map.unions (lpNewBuildCache lp : addBuildCache) - TTUpstream _ _ -> return () + checkForUnlistedFiles taskType preBuildTime pkgDir when (doHaddock package) $ do announce "haddock" @@ -1093,6 +1080,21 @@ singleBuild runInBase ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} in return $ Just (dpGhcPkgId dp) _ -> error "singleBuild: invariant violated: multiple results when describing installed package" +-- | Check if any unlisted files have been found, and add them to the build cache. +checkForUnlistedFiles :: M env m => TaskType -> ModTime -> Path Abs Dir -> m () +checkForUnlistedFiles (TTLocal lp) preBuildTime pkgDir = do + (addBuildCache,warnings) <- + addUnlistedToBuildCache + preBuildTime + (lpPackage lp) + (lpCabalFile lp) + (lpNewBuildCache lp) + mapM_ ($logWarn . ("Warning: " <>) . T.pack . show) warnings + unless (null addBuildCache) $ + writeBuildCache pkgDir $ + Map.unions (lpNewBuildCache lp : addBuildCache) +checkForUnlistedFiles (TTUpstream _ _) _ _ = return () + -- | Determine if all of the dependencies given are installed depsPresent :: InstalledMap -> Map PackageName VersionRange -> Bool depsPresent installedMap deps = all @@ -1147,8 +1149,10 @@ singleTest runInBase topts lptb ac ee task installedMap = do TTLocal lp -> writeBuildCache pkgDir $ lpNewBuildCache lp TTUpstream _ _ -> assert False $ return () extraOpts <- extraBuildOptions (eeBuildOpts ee) + preBuildTime <- modTime <$> liftIO getCurrentTime cabal (console && configHideTHLoading config) $ "build" : (components ++ extraOpts) + checkForUnlistedFiles (taskType task) preBuildTime pkgDir setTestBuilt pkgDir toRun <- @@ -1292,7 +1296,9 @@ singleBench runInBase beopts _lptb ac ee task installedMap = do TTUpstream _ _ -> assert False $ return () config <- asks getConfig extraOpts <- extraBuildOptions (eeBuildOpts ee) + preBuildTime <- modTime <$> liftIO getCurrentTime cabal (console && configHideTHLoading config) ("build" : extraOpts) + checkForUnlistedFiles (taskType task) preBuildTime pkgDir setBenchBuilt pkgDir let args = maybe [] ((:[]) . ("--benchmark-options=" <>)) diff --git a/src/Stack/Build/Source.hs b/src/Stack/Build/Source.hs index 5e6a848249..7fcbc88b74 100644 --- a/src/Stack/Build/Source.hs +++ b/src/Stack/Build/Source.hs @@ -338,10 +338,10 @@ loadLocalPackage bopts targets (name, (lpv, gpkg)) = do benchpkg = resolvePackage benchconfig gpkg mbuildCache <- tryGetBuildCache $ lpvRoot lpv (files,_) <- getPackageFilesSimple pkg (lpvCabalFP lpv) - + -- Filter out the cabal_macros file to avoid spurious recompilations let filteredFiles = Set.filter ((/= $(mkRelFile "cabal_macros.h")) . filename) files - + (dirtyFiles, newBuildCache) <- checkBuildCache (fromMaybe Map.empty mbuildCache) (map toFilePath $ Set.toList filteredFiles) From c42f6257487a3f7947313669e841135f6175e251 Mon Sep 17 00:00:00 2001 From: Chris Done Date: Mon, 26 Oct 2015 09:57:37 +0100 Subject: [PATCH 095/106] Strip -static before passing to GHCi (#1094) --- src/Stack/Ghci.hs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Stack/Ghci.hs b/src/Stack/Ghci.hs index 88bad0896e..150258a3f0 100644 --- a/src/Stack/Ghci.hs +++ b/src/Stack/Ghci.hs @@ -14,6 +14,7 @@ import Control.Monad.IO.Class import Control.Monad.Logger import Control.Monad.Reader import Control.Monad.Trans.Resource +import Data.Either import Data.Function import Data.List import Data.Map.Strict (Map) @@ -269,13 +270,24 @@ makeGhciPkgInfo sourceMap installedMap locals name cabalfp components = do STLocalComps cs -> S.member k cs _ -> True) m) + filteredOptions = + nub (map + (\x -> + if badForGhci x + then Left x + else Right x) + (generalOpts <> + concat (filterWithinWantedComponents componentsOpts))) + case lefts filteredOptions of + [] -> return () + options -> + $logWarn + ("The following GHC options are incompatible with GHCi and have not been passed to it: " <> + T.unwords (map T.pack options)) return GhciPkgInfo { ghciPkgName = packageName pkg - , ghciPkgOpts = filter - (not . badForGhci) - (generalOpts <> - concat (filterWithinWantedComponents componentsOpts)) + , ghciPkgOpts = rights filteredOptions , ghciPkgDir = parent cabalfp , ghciPkgModules = mconcat (filterWithinWantedComponents componentsModules) @@ -290,5 +302,5 @@ makeGhciPkgInfo sourceMap installedMap locals name cabalfp components = do where badForGhci :: String -> Bool badForGhci x = - isPrefixOf "-O" x || elem x (words "-debug -threaded -ticky") + isPrefixOf "-O" x || elem x (words "-debug -threaded -ticky -static") setMapMaybe f = S.fromList . mapMaybe f . S.toList From cf09cab0f40b69da5e177a08d2ce3ff533dc83c5 Mon Sep 17 00:00:00 2001 From: Neil Mitchell Date: Mon, 26 Oct 2015 09:01:18 +0000 Subject: [PATCH 096/106] Don't cache the GHC folder Experiments show caching the GHC folder makes appveyor go 2 to 3 minutes slower in the best case, and has a massively higher chance of falling over. Appveyor recommends the cache folders be < 100Mb, which this violates. Appveyor also zips the folders at the end, which is why caching is slower. --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 8da9d21878..42ab8a83e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,5 @@ cache: - "c:\\sr" # stack root, short paths == less problems -- "%LOCALAPPDATA%\\Programs\\stack" build: off From 374296c869ee2dfb98e1997391c9dc3fe0e1399c Mon Sep 17 00:00:00 2001 From: Neil Mitchell Date: Mon, 26 Oct 2015 09:02:38 +0000 Subject: [PATCH 097/106] Use stack setup so you can ignore most of the output A workaround for https://github.com/commercialhaskell/stack/issues/1212 --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 42ab8a83e4..aabcef8e85 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,6 +13,7 @@ environment: STACK_ROOT: "c:\\sr" test_script: +- stack setup > nul # The ugly echo "" hack is to avoid complaints about 0 being an invalid file # descriptor -- echo "" | stack --arch i386 --no-terminal --install-ghc test +- echo "" | stack --no-terminal test From ed517b0b2dd3f58fe5965b853995f039ee5cb291 Mon Sep 17 00:00:00 2001 From: Heather Date: Mon, 26 Oct 2015 17:31:19 +0400 Subject: [PATCH 098/106] Control/Concurrent/Execute.hs : redundant do --- src/Control/Concurrent/Execute.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Control/Concurrent/Execute.hs b/src/Control/Concurrent/Execute.hs index 31f912f483..8ce0bb26c8 100644 --- a/src/Control/Concurrent/Execute.hs +++ b/src/Control/Concurrent/Execute.hs @@ -94,7 +94,7 @@ runActions' ExecuteState {..} = if null as then return $ return () else inner as - loop = join $ atomically $ breakOnErrs $ withActions $ \as -> do + loop = join $ atomically $ breakOnErrs $ withActions $ \as -> case break (Set.null . actionDeps) as of (_, []) -> do inAction <- readTVar esInAction From 1e48c96f620997ed848acb96c9868a6fabdf686b Mon Sep 17 00:00:00 2001 From: Heather Date: Tue, 27 Oct 2015 10:36:56 +0400 Subject: [PATCH 099/106] replace if then else with case matching (multiway if) --- src/Path/Find.hs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Path/Find.hs b/src/Path/Find.hs index 11e1e5fe15..15f9b8b716 100644 --- a/src/Path/Find.hs +++ b/src/Path/Find.hs @@ -45,15 +45,9 @@ findPathUp pathType dir p upperBound = do entries <- listDirectory dir case find p (pathType entries) of Just path -> return (Just path) - Nothing -> - if Just dir == upperBound - then return Nothing - else if parent dir == dir - then return Nothing - else findPathUp pathType - (parent dir) - p - upperBound + Nothing | Just dir == upperBound -> return Nothing + | parent dir == dir -> return Nothing + | otherwise -> findPathUp pathType (parent dir) p upperBound -- | Find files matching predicate below a root directory. findFiles :: Path Abs Dir -- ^ Root directory to begin with. From b75829617fbf4e1edbc89c9c87c443c5f3954745 Mon Sep 17 00:00:00 2001 From: Chris Done Date: Tue, 27 Oct 2015 13:49:42 +0100 Subject: [PATCH 100/106] Import all modules after loading them (#995) --- src/Stack/Ghci.hs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Stack/Ghci.hs b/src/Stack/Ghci.hs index 150258a3f0..a8142fa459 100644 --- a/src/Stack/Ghci.hs +++ b/src/Stack/Ghci.hs @@ -29,6 +29,7 @@ import Distribution.ModuleName (ModuleName) import Distribution.Text (display) import Network.HTTP.Client.Conduit import Path +import Path.IO import Prelude import Stack.Build import Stack.Build.Installed @@ -39,6 +40,7 @@ import Stack.Exec import Stack.Package import Stack.Types import Stack.Types.Internal +import System.Directory (getTemporaryDirectory) -- | Command-line options for GHC. data GhciOpts = GhciOpts @@ -73,10 +75,11 @@ ghci GhciOpts{..} = do mainFile <- figureOutMainFile mainIsTargets targets pkgs wc <- getWhichCompiler let pkgopts = concatMap ghciPkgOpts pkgs - srcfiles + modulesToLoad | ghciNoLoadModules = [] | otherwise = - nub (maybe [] (return . toFilePath) mainFile <> + nub + (maybe [] (return . toFilePath) mainFile <> concatMap (map display . S.toList . ghciPkgModules) pkgs) odir = [ "-odir=" <> toFilePath (objectInterfaceDir bconfig) @@ -84,10 +87,23 @@ ghci GhciOpts{..} = do $logInfo ("Configuring GHCi with the following packages: " <> T.intercalate ", " (map (packageNameText . ghciPkgName) pkgs)) - exec - defaultEnvSettings - (fromMaybe (compilerExeName wc) ghciGhcCommand) - ("--interactive" : odir <> pkgopts <> srcfiles <> ghciArgs) + tmp <- liftIO getTemporaryDirectory + withCanonicalizedTempDirectory + tmp + "ghci-script" + (\tmpDir -> + do let scriptPath = tmpDir $(mkRelFile "ghci-script") + fp = toFilePath scriptPath + loadModules = ":l " <> unwords modulesToLoad + bringIntoScope = ":m + " <> unwords modulesToLoad + liftIO (writeFile fp (unlines [loadModules,bringIntoScope])) + finally (exec + defaultEnvSettings + (fromMaybe (compilerExeName wc) ghciGhcCommand) + ("--interactive" : + odir <> pkgopts <> ghciArgs <> + ["-ghci-script=" <> fp])) + (removeFile scriptPath)) -- | Figure out the main-is file to load based on the targets. Sometimes there -- is none, sometimes it's unambiguous, sometimes it's From 133f858b89e6186964bc926bc91066ec561991ce Mon Sep 17 00:00:00 2001 From: Emanuel Borsboom Date: Tue, 27 Oct 2015 11:00:42 -0700 Subject: [PATCH 101/106] Move Windows installers above manual download --- doc/install_and_upgrade.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md index 80c08136c2..6d44063ef7 100644 --- a/doc/install_and_upgrade.md +++ b/doc/install_and_upgrade.md @@ -20,16 +20,26 @@ find links that always point to the latest bindists variable similarly to your root (e.g., `set STACK_ROOT=c:\stack_root`) *before* running `stack`. +*Note:* while generally 32-bit GHC is better tested on Windows, there are +reports that recent versions of Windows only work with the 64-bit version of +Stack (see +[issue #393](https://github.com/commercialhaskell/stack/issues/393)). + +### Installer + +We recommend installing to the default location with these installers, as that +will make `stack install` and `stack upgrade` work correctly out of the box. + + * [Windows 32-bit Installer](https://www.stackage.org/stack/windows-i386-installer) + * [Windows 64-bit Installer](https://www.stackage.org/stack/windows-x86_64-installer) + +### Manual download + * Download the latest release: * [Windows 32-bit](https://www.stackage.org/stack/windows-i386) * [Windows 64-bit](https://www.stackage.org/stack/windows-x86_64) - Note: while generally 32-bit GHC is better tested on Windows, there are - reports that recent versions of Windows only work with the 64-bit version of - stack (see - [issue #393](https://github.com/commercialhaskell/stack/issues/393)). - * Unpack the archive and place `stack.exe` somewhere on your `%PATH%` (see [Path section below](#path)) and you can then run `stack` on the command line. @@ -40,14 +50,6 @@ NOTE: These executables have been built and tested on a Windows 7, 8.1, and 10 been tested. If you do test, please edit and update this page to indicate as such. -### Installer (experimental) - -We recommend installing to the default location with these installers, as that -will make `stack install` and `stack upgrade` work correctly out of the box. - - * [Windows 32-bit Installer](https://www.stackage.org/stack/windows-i386-installer) (experimental) - * [Windows 64-bit Installer](https://www.stackage.org/stack/windows-x86_64-installer) (experimental) - ## Mac OS X ### Using brew From be015b5309a3a57271891ece4b22e14cc3abd62d Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Fri, 23 Oct 2015 19:04:09 -0700 Subject: [PATCH 102/106] Only ask for commit count once when compiling --- src/main/Main.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/Main.hs b/src/main/Main.hs index a874d706fb..9ab5aa8fa4 100644 --- a/src/main/Main.hs +++ b/src/main/Main.hs @@ -110,12 +110,13 @@ main = withInterpreterArgs stackProgName $ \args isInterpreter -> do dockerHelpOptName (dockerOptsParser True) ("Only showing --" ++ Docker.dockerCmdName ++ "* options.") - let versionString' = concat $ concat + let commitCount = $gitCommitCount + versionString' = concat $ concat [ [$(simpleVersion Meta.version)] -- Leave out number of commits for --depth=1 clone -- See https://github.com/commercialhaskell/stack/issues/792 - , [" (" ++ $gitCommitCount ++ " commits)" | $gitCommitCount /= ("1"::String) && - $gitCommitCount /= ("UNKNOWN" :: String)] + , [" (" ++ commitCount ++ " commits)" | commitCount /= ("1"::String) && + commitCount /= ("UNKNOWN" :: String)] , [" ", display buildArch] ] From a873635350f2f56dbe813649865ff828fa9455ba Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 27 Oct 2015 19:48:43 -0700 Subject: [PATCH 103/106] Fix a copy-o which breaks ghci test targets #1222 --- src/Stack/Package.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index 40fdaee73c..8b0042b9fb 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -277,7 +277,7 @@ generatePkgDescOpts sourceMap installedMap locals cabalfp pkg componentPaths = d , map (\test -> (generate - (CBench (T.pack (testName test))) + (CTest (T.pack (testName test))) (testBuildInfo test))) (testSuites pkg)]) , ["-hide-all-packages"]) From c102b5b5ef26a81b461ae941298a383634e9a716 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 27 Oct 2015 20:24:48 -0700 Subject: [PATCH 104/106] Minor change to some local var naming --- src/Stack/Ghci.hs | 8 ++++---- src/Stack/Package.hs | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Stack/Ghci.hs b/src/Stack/Ghci.hs index a8142fa459..8f0ca8b08d 100644 --- a/src/Stack/Ghci.hs +++ b/src/Stack/Ghci.hs @@ -217,8 +217,8 @@ ghciSetup mainIs stringTargets = do else return Nothing infos <- forM locals $ - \(name,(cabalfp,components)) -> - makeGhciPkgInfo sourceMap installedMap (map fst locals) name cabalfp components + \(name,(cabalfp,component)) -> + makeGhciPkgInfo sourceMap installedMap (map fst locals) name cabalfp component unless (M.null realTargets) (build (const (return ())) Nothing bopts) return (realTargets, mainIsTargets, infos) where @@ -263,7 +263,7 @@ makeGhciPkgInfo -> Path Abs File -> SimpleTarget -> m GhciPkgInfo -makeGhciPkgInfo sourceMap installedMap locals name cabalfp components = do +makeGhciPkgInfo sourceMap installedMap locals name cabalfp component = do econfig <- asks getEnvConfig bconfig <- asks getBuildConfig let config = @@ -282,7 +282,7 @@ makeGhciPkgInfo sourceMap installedMap locals name cabalfp components = do M.elems (M.filterWithKey (\k _ -> - case components of + case component of STLocalComps cs -> S.member k cs _ -> True) m) diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index 8b0042b9fb..cd212354dc 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -196,10 +196,10 @@ resolvePackage packageConfig gpkg = [T.pack (exeName b) | b <- executables pkg , buildable (buildInfo b)] , packageOpts = GetPackageOpts $ - \sourceMap installedMap locals cabalfp -> + \sourceMap installedMap omitPkgs cabalfp -> do (componentsModules,componentFiles,_,_) <- getPackageFiles pkgFiles cabalfp (componentsOpts,generalOpts) <- - generatePkgDescOpts sourceMap installedMap locals cabalfp pkg componentFiles + generatePkgDescOpts sourceMap installedMap omitPkgs cabalfp pkg componentFiles return (componentsModules,componentFiles,componentsOpts,generalOpts) , packageHasExposedModules = maybe False @@ -230,12 +230,12 @@ generatePkgDescOpts :: (HasEnvConfig env, HasPlatform env, MonadThrow m, MonadReader env m, MonadIO m) => SourceMap -> InstalledMap - -> [PackageName] + -> [PackageName] -- ^ Packages to omit from the "-package" / "-package-id" flags -> Path Abs File -> PackageDescription -> Map NamedComponent (Set DotCabalPath) -> m (Map NamedComponent [String],[String]) -generatePkgDescOpts sourceMap installedMap locals cabalfp pkg componentPaths = do +generatePkgDescOpts sourceMap installedMap omitPkgs cabalfp pkg componentPaths = do distDir <- distDirFromDir cabalDir let cabalmacros = autogenDir distDir $(mkRelFile "cabal_macros.h") exists <- fileExists cabalmacros @@ -251,7 +251,7 @@ generatePkgDescOpts sourceMap installedMap locals cabalfp pkg componentPaths = d mcabalmacros cabalDir distDir - locals + omitPkgs binfo (fromMaybe mempty (M.lookup namedComponent componentPaths)) namedComponent) @@ -296,7 +296,7 @@ generateBuildInfoOpts -> Set DotCabalPath -> NamedComponent -> [String] -generateBuildInfoOpts sourceMap installedMap mcabalmacros cabalDir distDir locals b dotCabalPaths componentName = +generateBuildInfoOpts sourceMap installedMap mcabalmacros cabalDir distDir omitPkgs b dotCabalPaths componentName = nubOrd (concat [ghcOpts b, extOpts b, srcOpts, includeOpts, macros, deps, extra b, extraDirs, fworks b, cObjectFiles]) where cObjectFiles = @@ -313,7 +313,7 @@ generateBuildInfoOpts sourceMap installedMap mcabalmacros cabalDir distDir local ((("-" <>) . versionString) . sourceVersion) (M.lookup (fromCabalPackageName name) sourceMap)] | Dependency name _ <- targetBuildDepends b - , not (elem name (map toCabalPackageName locals))] + , not (elem name (map toCabalPackageName omitPkgs))] -- Generates: -package=base -package=base16-bytestring-0.1.1.6 ... sourceVersion (PSUpstream ver _ _) = ver sourceVersion (PSLocal localPkg) = packageVersion (lpPackage localPkg) From 588319334a2e47477b1a17ea77c1c506e85d91a9 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 27 Oct 2015 20:37:19 -0700 Subject: [PATCH 105/106] Fix passing of include dirs to GHCI #1222 --- src/Stack/Package.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs index cd212354dc..fca1be5d40 100644 --- a/src/Stack/Package.hs +++ b/src/Stack/Package.hs @@ -328,9 +328,12 @@ generateBuildInfoOpts sourceMap installedMap mcabalmacros cabalDir distDir omitP isGhc _ = False extOpts = map (("-X" ++) . display) . usedExtensions srcOpts = + -- This initial "-i" resets the include directories to not + -- include CWD. + "-i" : map (("-i" <>) . toFilePath) - (cabalDir : + ((if null (hsSourceDirs b) then [cabalDir] else []) <> map (cabalDir ) (mapMaybe parseRelDir (hsSourceDirs b)) <> [autogenDir distDir,buildDir distDir]) ++ ["-stubdir=" ++ toFilePath (buildDir distDir)] From d2a195a84bc466cbfeb8cf1721b3729dad540c43 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Tue, 27 Oct 2015 20:37:50 -0700 Subject: [PATCH 106/106] Fix ghci -package-id for lib dep from test #1222 --- src/Stack/Ghci.hs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Stack/Ghci.hs b/src/Stack/Ghci.hs index 8f0ca8b08d..77be604f91 100644 --- a/src/Stack/Ghci.hs +++ b/src/Stack/Ghci.hs @@ -215,13 +215,19 @@ ghciSetup mainIs stringTargets = do return (Just (name, (cabalfp, simpleTargets))) Nothing -> return Nothing else return Nothing + let localLibs = [name | (name, (_, target)) <- locals, targetIncludesLib target] infos <- forM locals $ \(name,(cabalfp,component)) -> - makeGhciPkgInfo sourceMap installedMap (map fst locals) name cabalfp component + makeGhciPkgInfo sourceMap installedMap localLibs name cabalfp component unless (M.null realTargets) (build (const (return ())) Nothing bopts) return (realTargets, mainIsTargets, infos) where + -- NOTE: this doesn't mean that the cabal package actually has a + -- library, just that if it does, the requested target includes it. + targetIncludesLib STLocalAll = True + targetIncludesLib (STLocalComps comps) = S.member CLib comps + targetIncludesLib _ = False makeBuildOpts targets = base { boptsTargets = stringTargets