diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -135,13 +135,13 @@
 Running the integration tests is a little involved, you'll need to:
 
 ```bash
-$ stack build --flag stack:integration-tests stack --interleaved-output --exec stack-integration-test
+$ stack build --flag stack:integration-tests stack --exec stack-integration-test
 ```
 
 Running an individual module works like this:
 
 ```bash
-$ stack build --flag stack:integration-tests stack --interleaved-output --exec "stack-integration-test -m <PATTERN>"
+$ stack build --flag stack:integration-tests stack --exec "stack-integration-test -m <PATTERN>"
 ```
 
 Where `<PATTERN>` is the name of the folder listed in the
diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,101 @@
 # Changelog
 
+## v2.3.1
 
+**Changes since v2.1.3.1**
+
+Release notes:
+* We have reduced the number of platforms that we support with binary releases.
+  The reason behind this is that we've been slowed down in our release process
+  until now with issues trying to build binaries for less common platforms. In
+  order to make sure we can address issues more quickly (like supporting new
+  GHC versions), we're limiting support from the Stack team to:
+
+    * Linux 64-bit (static)
+    * MacOS
+    * Windows 64-bit
+
+  If others want to provide additional binaries, we will definitely be happy
+  for the support. But since our CI system is currently able to produce these
+  three bindists only, that's what we will be providing with the next release.
+
+Major changes:
+* `setup-info-locations` yaml configuration now allows overwriting the default locations of `stack-setup-2.yaml`.
+  [#5031](https://github.com/commercialhaskell/stack/pull/5031)
+  [#2983](https://github.com/commercialhaskell/stack/issues/2983)
+  [#2913](https://github.com/commercialhaskell/stack/issues/2913)
+
+* The `setup-info` configuration key now allows overwriting parts of the default `setup-info`
+
+* The `--setup-info-yaml` command line flag now may be used in all stack commands such as `stack build`, and not only in `stack setup`
+
+* The `--setup-info-yaml` may specify multiple locations for `stack-setup.yaml` files.
+
+* The `stack upload` can read first reads environment Variable `$HACKAGE_USERNAME` and `$HACKAGE_PASSWORD` if they are missing only then asks for `username` or `password`
+
+* Fully remove GHCJS support.
+
+* Remove the `freeze` command. It has been replaced by lock files.
+
+Behavior changes:
+* Remove the deprecated `--stack-setup-yaml` command line argument in favor of `--setup-info-yaml`
+  [#2647](https://github.com/commercialhaskell/stack/issues/2647)
+
+* We now recommend checking in generated cabal files for repos. When generating lock files for
+  extra-deps that only include `package.yaml` files, a deprecation warning will be generated.
+  Also, those packages will no longer be included in the generated lock files.
+  See [#5210](https://github.com/commercialhaskell/stack/issues/5210).
+
+Other enhancements:
+* Add `build-output-timestamps` flag in yaml. Setting it to true
+  prefixes each build log output line with a timestamp.
+
+* Show warning about `local-programs-path` with spaces on windows
+  when running scripts. See 
+  [#5013](https://github.com/commercialhaskell/stack/pull/5013)
+
+* Add `ls dependencies json` which will print dependencies as JSON.
+  `ls dependencies --tree`  is now `ls dependencies tree`. See
+  [#4424](https://github.com/commercialhaskell/stack/pull/4424)
+
+* Remove warning for using Stack with GHC 8.8-8.10, and Cabal 3.0-3.2.
+
+* Allow relative paths in `--setup-info-yaml` and tool paths
+  [#3394](https://github.com/commercialhaskell/stack/issues/3394)
+
+* Added the `--only-locals` flag. See
+  [#5272](https://github.com/commercialhaskell/stack/issues/5272)
+
+Bug fixes:
+
+* Upgrade `pantry`: module mapping insertions into the database are now atomic.
+  Previously, if you SIGTERMed at the wrong time while running a script, you
+  could end up with an inconsistent database state.
+
+* `--resolver global` doesn't retrieve snapshots list from the internet
+   beause doesn't need it. See [#5103](https://github.com/commercialhaskell/stack/issues/5103)
+
+* Fix using relative links in haddocks output.  See
+  [#4971](https://github.com/commercialhaskell/stack/issues/4971).
+* Do not include generated cabal file information in lock files. See
+  [#5045](https://github.com/commercialhaskell/stack/issues/5045).
+
+* Use proper Hoogle executable path when installed automatically. See
+  [#4905](https://github.com/commercialhaskell/stack/issues/4905)
+
+* Fix GHC version for batched package unregistration. See
+  [#4951](https://github.com/commercialhaskell/stack/issues/4951)
+
+* Use Hoogle from the snapshot used and not the latest version. See
+  [#4905](https://github.com/commercialhaskell/stack/issues/4905)
+
+* Resolve "'stty' is not recognized". See
+  [#4901](https://github.com/commercialhaskell/stack/issues/4901)
+
+* Fix missing reconfigure check causing errors when a package gets
+  used in multiple projects. See
+  [#5147](https://github.com/commercialhaskell/stack/issues/5147)
+
 ## v2.1.3.1
 
 Hackage-only release:
@@ -9,6 +104,7 @@
 * Support rio-0.1.11.0
 * Add `stack.yaml` back to hackage sdist, and add `snapshot.yaml`
 
+
 ## v2.1.3
 
 **Changes since v2.1.1**
@@ -59,7 +155,7 @@
 * Expose package library when running tests.
 
 * Fix support for non-ASCII module names. See
-  [4938](https://github.com/commercialhaskell/stack/issues/4938)
+  [#4938](https://github.com/commercialhaskell/stack/issues/4938)
 
 Other changes:
 
@@ -202,7 +298,7 @@
   use to avoid multiple runs of Stack from trampling each others'
   files. See
   [#2730](https://github.com/commercialhaskell/stack/issues/2730).
-* Stack will check occassionally if there is a new version available and prompt
+* Stack will check occasionally if there is a new version available and prompt
   the user to upgrade. This will not incur any additional network traffic, as
   it will piggy-back on the existing Hackage index updates. You can set
   `recommend-stack-upgrade: false` to bypass this. See
@@ -233,7 +329,7 @@
 * British English spelling of 'color' (colour) accepted as an alias for
   `--color`, `--stack-colors`, `stack ls stack-colors` at the command line and
   for `color:` and `stack-colors:` in yaml configuration files.
-* New build option `--ddump-dir`. (See 
+* New build option `--ddump-dir`. (See
   [#4225](https://github.com/commercialhaskell/stack/issues/4225))
 * Stack parses and respects the `preferred-versions` information from
   Hackage for choosing latest version of a package in some cases,
@@ -678,7 +774,7 @@
   conflicting versions of packages without issue. See
   [Stackage issue #3185](https://github.com/fpco/stackage/issues/3185).
 * When promoting packages from snapshot to local, we were
-  occassionally discarding the actual package location content and
+  occasionally discarding the actual package location content and
   instead defaulting to pulling the package from the index. We now
   correctly retain this information. Note that if you were affected by
   this bug, you will likely need to delete the binary build cache
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -8,13 +8,3 @@
 
 See [haskellstack.org](http://haskellstack.org) or the [doc](./doc) directory for more
 information.
-
-### Subsystem maintainers
-
-* GHCJS - [Matchwood](https://github.com/matchwood)
-
-NOTE: GHCJS support is considered experimental. In Stack 2.0, we are
-removing support for building GHCJS itself; links will be added to
-this README for information on separate tools. Issues on GHCJS may be
-closed as not supported, and the next major Stack release may remove
-GHCJS support entirely.
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -3,19 +3,19 @@
 
 import Data.List ( nub, sortBy )
 import Data.Ord ( comparing )
-import Distribution.Package ( PackageId, InstalledPackageId, packageVersion, packageName )
+import Distribution.Package ( PackageId, UnitId, packageVersion, packageName )
 import Distribution.PackageDescription ( PackageDescription(), Executable(..) )
-import Distribution.InstalledPackageInfo (sourcePackageId, installedPackageId)
+import Distribution.InstalledPackageInfo (sourcePackageId, installedUnitId)
 import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )
-import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )
-import Distribution.Simple.BuildPaths ( autogenModulesDir )
+import Distribution.Simple.Utils ( rewriteFileEx, createDirectoryIfMissingVerbose )
+import Distribution.Simple.BuildPaths ( autogenPackageModulesDir )
 import Distribution.Simple.PackageIndex (allPackages, dependencyClosure)
 import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )
 import Distribution.Simple.LocalBuildInfo ( installedPkgs, withLibLBI, withExeLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )
 import Distribution.Types.PackageName (PackageName, unPackageName)
 import Distribution.Types.UnqualComponentName (unUnqualComponentName)
-import Distribution.Verbosity ( Verbosity )
-import Distribution.Version ( showVersion )
+import Distribution.Verbosity ( Verbosity, normal )
+import Distribution.Pretty ( prettyShow )
 import System.FilePath ( (</>) )
 
 main :: IO ()
@@ -27,11 +27,11 @@
 
 generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()
 generateBuildModule verbosity pkg lbi = do
-  let dir = autogenModulesDir lbi
+  let dir = autogenPackageModulesDir lbi
   createDirectoryIfMissingVerbose verbosity True dir
   withLibLBI pkg lbi $ \_ libcfg -> do
     withExeLBI pkg lbi $ \exe clbi ->
-      rewriteFile (dir </> "Build_" ++ exeName' exe ++ ".hs") $ unlines
+      rewriteFileEx normal (dir </> "Build_" ++ exeName' exe ++ ".hs") $ unlines
         [ "module Build_" ++ exeName' exe ++ " where"
         , ""
         , "deps :: [String]"
@@ -40,13 +40,13 @@
   where
     exeName' = unUnqualComponentName . exeName
     formatdeps = map formatone . sortBy (comparing unPackageName')
-    formatone p = unPackageName' p ++ "-" ++ showVersion (packageVersion p)
+    formatone p = unPackageName' p ++ "-" ++ prettyShow (packageVersion p)
     unPackageName' = unPackageName . packageName
     transDeps xs ys =
       either (map sourcePackageId . allPackages) handleDepClosureFailure $ dependencyClosure allInstPkgsIdx availInstPkgIds
       where
         allInstPkgsIdx = installedPkgs lbi
-        allInstPkgIds = map installedPackageId $ allPackages allInstPkgsIdx
+        allInstPkgIds = map installedUnitId $ allPackages allInstPkgsIdx
         -- instPkgIds includes `stack-X.X.X`, which is not a dependency hence is missing from allInstPkgsIdx. Filter that out.
         availInstPkgIds = filter (`elem` allInstPkgIds) $ testDeps xs ys
         handleDepClosureFailure unsatisfied =
@@ -54,5 +54,5 @@
             "Computation of transitive dependencies failed." ++
             if null unsatisfied then "" else " Unresolved dependencies: " ++ show unsatisfied
 
-testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [InstalledPackageId]
+testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [UnitId]
 testDeps xs ys = map fst $ nub $ componentPackageDeps xs ++ componentPackageDeps ys
diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md
--- a/doc/CONTRIBUTING.md
+++ b/doc/CONTRIBUTING.md
@@ -135,13 +135,13 @@
 Running the integration tests is a little involved, you'll need to:
 
 ```bash
-$ stack build --flag stack:integration-tests stack --interleaved-output --exec stack-integration-test
+$ stack build --flag stack:integration-tests stack --exec stack-integration-test
 ```
 
 Running an individual module works like this:
 
 ```bash
-$ stack build --flag stack:integration-tests stack --interleaved-output --exec "stack-integration-test -m <PATTERN>"
+$ stack build --flag stack:integration-tests stack --exec "stack-integration-test -m <PATTERN>"
 ```
 
 Where `<PATTERN>` is the name of the folder listed in the
diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md
--- a/doc/ChangeLog.md
+++ b/doc/ChangeLog.md
@@ -1,6 +1,101 @@
 # Changelog
 
+## v2.3.1
 
+**Changes since v2.1.3.1**
+
+Release notes:
+* We have reduced the number of platforms that we support with binary releases.
+  The reason behind this is that we've been slowed down in our release process
+  until now with issues trying to build binaries for less common platforms. In
+  order to make sure we can address issues more quickly (like supporting new
+  GHC versions), we're limiting support from the Stack team to:
+
+    * Linux 64-bit (static)
+    * MacOS
+    * Windows 64-bit
+
+  If others want to provide additional binaries, we will definitely be happy
+  for the support. But since our CI system is currently able to produce these
+  three bindists only, that's what we will be providing with the next release.
+
+Major changes:
+* `setup-info-locations` yaml configuration now allows overwriting the default locations of `stack-setup-2.yaml`.
+  [#5031](https://github.com/commercialhaskell/stack/pull/5031)
+  [#2983](https://github.com/commercialhaskell/stack/issues/2983)
+  [#2913](https://github.com/commercialhaskell/stack/issues/2913)
+
+* The `setup-info` configuration key now allows overwriting parts of the default `setup-info`
+
+* The `--setup-info-yaml` command line flag now may be used in all stack commands such as `stack build`, and not only in `stack setup`
+
+* The `--setup-info-yaml` may specify multiple locations for `stack-setup.yaml` files.
+
+* The `stack upload` can read first reads environment Variable `$HACKAGE_USERNAME` and `$HACKAGE_PASSWORD` if they are missing only then asks for `username` or `password`
+
+* Fully remove GHCJS support.
+
+* Remove the `freeze` command. It has been replaced by lock files.
+
+Behavior changes:
+* Remove the deprecated `--stack-setup-yaml` command line argument in favor of `--setup-info-yaml`
+  [#2647](https://github.com/commercialhaskell/stack/issues/2647)
+
+* We now recommend checking in generated cabal files for repos. When generating lock files for
+  extra-deps that only include `package.yaml` files, a deprecation warning will be generated.
+  Also, those packages will no longer be included in the generated lock files.
+  See [#5210](https://github.com/commercialhaskell/stack/issues/5210).
+
+Other enhancements:
+* Add `build-output-timestamps` flag in yaml. Setting it to true
+  prefixes each build log output line with a timestamp.
+
+* Show warning about `local-programs-path` with spaces on windows
+  when running scripts. See 
+  [#5013](https://github.com/commercialhaskell/stack/pull/5013)
+
+* Add `ls dependencies json` which will print dependencies as JSON.
+  `ls dependencies --tree`  is now `ls dependencies tree`. See
+  [#4424](https://github.com/commercialhaskell/stack/pull/4424)
+
+* Remove warning for using Stack with GHC 8.8-8.10, and Cabal 3.0-3.2.
+
+* Allow relative paths in `--setup-info-yaml` and tool paths
+  [#3394](https://github.com/commercialhaskell/stack/issues/3394)
+
+* Added the `--only-locals` flag. See
+  [#5272](https://github.com/commercialhaskell/stack/issues/5272)
+
+Bug fixes:
+
+* Upgrade `pantry`: module mapping insertions into the database are now atomic.
+  Previously, if you SIGTERMed at the wrong time while running a script, you
+  could end up with an inconsistent database state.
+
+* `--resolver global` doesn't retrieve snapshots list from the internet
+   beause doesn't need it. See [#5103](https://github.com/commercialhaskell/stack/issues/5103)
+
+* Fix using relative links in haddocks output.  See
+  [#4971](https://github.com/commercialhaskell/stack/issues/4971).
+* Do not include generated cabal file information in lock files. See
+  [#5045](https://github.com/commercialhaskell/stack/issues/5045).
+
+* Use proper Hoogle executable path when installed automatically. See
+  [#4905](https://github.com/commercialhaskell/stack/issues/4905)
+
+* Fix GHC version for batched package unregistration. See
+  [#4951](https://github.com/commercialhaskell/stack/issues/4951)
+
+* Use Hoogle from the snapshot used and not the latest version. See
+  [#4905](https://github.com/commercialhaskell/stack/issues/4905)
+
+* Resolve "'stty' is not recognized". See
+  [#4901](https://github.com/commercialhaskell/stack/issues/4901)
+
+* Fix missing reconfigure check causing errors when a package gets
+  used in multiple projects. See
+  [#5147](https://github.com/commercialhaskell/stack/issues/5147)
+
 ## v2.1.3.1
 
 Hackage-only release:
@@ -9,6 +104,7 @@
 * Support rio-0.1.11.0
 * Add `stack.yaml` back to hackage sdist, and add `snapshot.yaml`
 
+
 ## v2.1.3
 
 **Changes since v2.1.1**
@@ -59,7 +155,7 @@
 * Expose package library when running tests.
 
 * Fix support for non-ASCII module names. See
-  [4938](https://github.com/commercialhaskell/stack/issues/4938)
+  [#4938](https://github.com/commercialhaskell/stack/issues/4938)
 
 Other changes:
 
@@ -202,7 +298,7 @@
   use to avoid multiple runs of Stack from trampling each others'
   files. See
   [#2730](https://github.com/commercialhaskell/stack/issues/2730).
-* Stack will check occassionally if there is a new version available and prompt
+* Stack will check occasionally if there is a new version available and prompt
   the user to upgrade. This will not incur any additional network traffic, as
   it will piggy-back on the existing Hackage index updates. You can set
   `recommend-stack-upgrade: false` to bypass this. See
@@ -233,7 +329,7 @@
 * British English spelling of 'color' (colour) accepted as an alias for
   `--color`, `--stack-colors`, `stack ls stack-colors` at the command line and
   for `color:` and `stack-colors:` in yaml configuration files.
-* New build option `--ddump-dir`. (See 
+* New build option `--ddump-dir`. (See
   [#4225](https://github.com/commercialhaskell/stack/issues/4225))
 * Stack parses and respects the `preferred-versions` information from
   Hackage for choosing latest version of a package in some cases,
@@ -678,7 +774,7 @@
   conflicting versions of packages without issue. See
   [Stackage issue #3185](https://github.com/fpco/stackage/issues/3185).
 * When promoting packages from snapshot to local, we were
-  occassionally discarding the actual package location content and
+  occasionally discarding the actual package location content and
   instead defaulting to pulling the package from the index. We now
   correctly retain this information. Note that if you were affected by
   this bug, you will likely need to delete the binary build cache
diff --git a/doc/GUIDE.md b/doc/GUIDE.md
--- a/doc/GUIDE.md
+++ b/doc/GUIDE.md
@@ -450,7 +450,7 @@
 also known as *snapshots*. We mentioned the LTS resolvers, and you can get quite a bit of
 information about it at [https://www.stackage.org/lts](https://www.stackage.org/lts), including:
 
-* The appropriate resolver value (`resolver: lts-11.22`, as is currently the latest LTS)
+* The appropriate resolver value (`resolver: lts-14.27`, as is currently the latest LTS)
 * The GHC version used
 * A full list of all packages available in this snapshot
 * The ability to perform a Hoogle search on the packages in this snapshot
@@ -467,15 +467,15 @@
 
 ## Resolvers and changing your compiler version
 
-Let's explore package sets a bit further. Instead of lts-11.22, let's change our
+Let's explore package sets a bit further. Instead of lts-14.27, let's change our
 `stack.yaml` file to use [the latest nightly](https://www.stackage.org/nightly). Right now,
-this is currently 2018-07-25 - please see the resolve from the link above to get the latest.
+this is currently 2020-03-24 - please see the resolve from the link above to get the latest.
 
 Then, Rerunning `stack build` will produce:
 
 ```
 michael@d30748af6d3d:~/helloworld$ stack build
-Downloaded nightly-2018-07-31 build plan.
+Downloaded nightly-2020-03-24 build plan.
 # build output ...
 ```
 
@@ -483,8 +483,8 @@
 Continuous Integration (CI) setting, like on Travis. For example:
 
 ```
-michael@d30748af6d3d:~/helloworld$ stack --resolver lts-11.22 build
-Downloaded lts-11.22 build plan.
+michael@d30748af6d3d:~/helloworld$ stack --resolver lts-14.27 build
+Downloaded lts-14.27 build plan.
 # build output ...
 ```
 
@@ -520,7 +520,6 @@
 At the time of writing:
 
 * `ghc-X.Y.Z`, for requiring a specific GHC version but no additional packages
-* Experimental GHCJS support
 * Experimental custom snapshot support
 
 The most up-to-date information can always be found in the
@@ -541,7 +540,7 @@
 ```
 
 Note that you can also unpack to the directory of your liking instead of
-the current one by issueing:
+the current one by issuing:
 
 ```
 cueball:~$ stack unpack yackage-0.8.0 --to ~/work
@@ -574,45 +573,6 @@
 
 (Note: yackage does not currently support hpack, but you can also hpack-convert should you need to generate a package.yaml).
 
-#### External Dependencies
-
-Given that LTS Haskell and Stackage Nightly have ~1400 of the most common
-Haskell packages, this will often be enough to build most packages. However,
-at times, you may find that not all dependencies required may be available in
-the Stackage snapshots.
-
-Let's simulate an unsatisfied dependency by adding acme-missiles to the list of dependencies
-the build requires. This is done by including it in the `Build-depends` section in the .cabal file
-and then re-initing:
-
-```
-cueball:~/yackage-0.8.0$ stack init --force
-# init failure output
-```
-
-stack has tested six different snapshots, and in every case discovered that
-acme-missiles is not available. In the end it suggested that you use the
-`--solver` command line switch if you want to use packages outside Stackage. So
-let's give it a try:
-
-```
-cueball:~/yackage-0.8.0$ stack init --force --solver
-# solver output ...
-```
-
-stack will complain that it needs a `cabal-install` installation. Let's get that:
-
-```
-cueball:~/yackage-0.8.0$ stack install cabal-install
-```
-
-Then run the above `stack init` command again and it will succeed.
-
-As you can verify by viewing `stack.yaml`, three external dependencies were added
-by stack init under the `extra-deps` field. Of course, you could have added the
-external dependencies by manually editing `stack.yaml` but stack init does the
-hard work for you.
-
 #### Excluded Packages
 
 Sometimes multiple packages in your project may have conflicting requirements.
@@ -626,10 +586,10 @@
 To simulate a conflict we will use acme-missiles-0.3 in yackage and we will
 also copy `yackage.cabal` to another directory and change the name of the file
 and package to yackage-test. In this new package we will use acme-missiles-0.2
-instead. Let's see what happens when we run solver:
+instead. Let's see what happens when we re-run stack init:
 
 ```
-cueball:~/yackage-0.8.0$ stack init --force --solver --omit-packages
+cueball:~/yackage-0.8.0$ stack init --force --omit-packages
 # init failure output ...
 ```
 
@@ -697,70 +657,6 @@
 Warning: Specified resolver could not satisfy all dependencies. Some external packages have been added as dependencies.
 You can suppress this message by removing it from stack.yaml
 ```
-### stack solver
-
-While `stack init` is used to create stack configuration file from existing
-cabal files, `stack solver` can be used to fine tune or fix an existing stack
-configuration file.
-
-`stack solver` uses the existing file as a constraint. For example it will
-use only those packages specified in the existing config file or use existing
-external dependencies as constraints to figure out other dependencies.
-
-Let's try `stack solver` to verify the config that we generated earlier with
-`stack init`:
-
-```
-cueball:~/yackage-0.8.0$ stack solver
-# solver output ...
-```
-
-It says there are no changes needed to your configuration. Notice that it also reports
-`example/yackage-test.cabal` as missing from the config. It was purposely
-omitted by `stack init` to resolve a conflict.
-
-Sometimes `stack init` may not be able to give you a perfect configuration. In
-that case, you can tweak the configuration file as per your requirements and then
-run `stack solver`, it will check the file and suggest or apply any fixes
-needed.
-
-For example, if `stack init` ignored certain packages due to name conflicts or
-dependency conflicts, the choice that `stack init` made may not be the correct
-one. In that case you can revert the choice and use solver to fix things.
-
-Let's try commenting out `.` and uncommenting `examples/` in our previously
-generated `stack.yaml` and then run `stack solver`:
-
-```
-cueball:~/yackage-0.8.0$ stack solver
-# solver failure output ...
-```
-
-Due to the change that we made, solver suggested some new dependencies.
-By default it does not make changes to the config. As it suggested you can use
-`--update-config` to make changes to the config.
-
-NOTE: You should probably back up your `stack.yaml` before doing this, such as
-committing to Git/Mercurial/Darcs.
-
-Sometimes, you may want to use specific versions of certain packages for your
-project. To do that you can fix those versions by specifying them in the
-extra-deps section and then use `stack solver` to figure out whether it is
-feasible to use those or what other dependencies are needed as a result.
-
-If you want to change the resolver for your project, you can run
-`stack solver --resolver <resolver name>` and it will figure out the changes needed for you.
-
-Let's see what happens if we change the resolver to an older resolver - lts-2.22:
-
-```
-cueball:~/yackage-0.8.0$ stack solver --resolver lts-2.22
-# solver failure output ...
-```
-
-As you can see, it automatically suggested changes in `extra-deps` due to the
-change of resolver.
-
 ## Different databases
 
 Time to take a short break from hands-on examples and discuss a little
@@ -1247,7 +1143,7 @@
 ```
 michael@d30748af6d3d:~$ stack exec --package stm -- echo I installed the stm package via --package stm
 Run from outside a project, using implicit global project config
-Using latest snapshot resolver: lts-3.2
+Using latest snapshot resolver: lts-14.27
 Writing global (non-project-specific) config file to: /home/michael/.stack/global/stack.yaml
 Note: You can change the snapshot via the resolver field there.
 I installed the stm package via --package stm
@@ -1427,6 +1323,16 @@
 project and want to access the package databases and configurations used by
 that project. See the next section for more information on configuration files.
 
+### Platform-specific script issues
+
+On Mac OSX:
+
+- Avoid `{-# LANGUAGE CPP #-}` in stack scripts; it breaks the hashbang line
+  ([GHC #6132](https://gitlab.haskell.org/ghc/ghc/issues/6132))
+
+- Use a compiled executable, not another script, in the hashbang line.
+  Eg `#!/usr/bin/env runhaskell` will work but `#!/usr/local/bin/runhaskell` would not.
+
 ### Loading scripts in ghci
 
 Sometimes you want to load your script in ghci REPL to play around with your
@@ -1732,9 +1638,7 @@
 
 * `stack update` will download the most recent set of packages from your package
   indices (e.g. Hackage). Generally, stack runs this for you automatically
-  when necessary, but it can be useful to do this manually sometimes (e.g.,
-  before running `stack solver`, to guarantee you have the most recent
-  upstream packages available).
+  when necessary, but it can be useful to do this manually sometimes.
 * `stack unpack` is a command we've already used quite a bit for examples, but
   most users won't use it regularly. It does what you'd expect: downloads a
   tarball and unpacks it. It accept optional `--to` argument to specify
@@ -1746,6 +1650,13 @@
   per
   [our blog post](https://www.fpcomplete.com/blog/2016/05/stack-security-gnupg-keys).
     * `--no-signature` disables signing of packages
+    * `username` and `password` can be read by environment
+
+    ```bash
+    export $HACKAGE_USERNAME="<username>"
+    export $HACKAGE_PASSWORD="<password>"
+    ```
+
 * `stack upgrade` will build a new version of stack from source.
     * `--git` is a convenient way to get the most recent version from master for
       those testing and living on the bleeding edge.
@@ -1778,7 +1689,7 @@
 To create a profiling report for an executable, e.g. `my-exe`, you can
 run
 
-     stack exec -- my-exe +RTS -p
+     stack exec --profile -- my-exe +RTS -p
 
 For more fine-grained control of compilation options there are the
 `--library-profiling` and `--executable-profiling` flags which will turn on the
@@ -1809,13 +1720,11 @@
 use the `--trace` flag. Like `--profile` this compiles with profiling options,
 but adds the `+RTS -xc` runtime option.
 
-### DWARF
+### Debugging symbols
 
-`stack` now supports debugging and profiling with
-[DWARF information](https://ghc.haskell.org/trac/ghc/wiki/DWARF),
-using the `--no-strip`, `--no-library-stripping`, and `--no-executable-stripping`
-flags to disable the default behavior of removing such information from compiled
-libraries and executables.
+Building with debugging symbols in the [DWARF information](https://ghc.haskell.org/trac/ghc/wiki/DWARF) is supported by `stack`. This can be done by passing the flag `--ghc-options="-g"` and also to override the default behaviour of stripping executables of debugging symbols by passing either one of the following flags: `--no-strip`, `--no-library-stripping` or `--no-executable-stripping`.
+
+In Windows GDB can be isntalled to debug an executable with `stack exec -- pacman -S gdb`. Windows visual studio compiler's debugging format PDB is not supported at the moment. This might be possible by [separating](https://stackoverflow.com/questions/866721/how-to-generate-gcc-debug-symbol-outside-the-build-target) debugging symbols and [converting](https://github.com/rainers/cv2pdb) their format. Or as an option when [using the LLVM backend](http://blog.llvm.org/2017/08/llvm-on-windows-now-supports-pdb-debug.html).
 
 ## More resources
 
diff --git a/doc/SIGNING_KEY.md b/doc/SIGNING_KEY.md
--- a/doc/SIGNING_KEY.md
+++ b/doc/SIGNING_KEY.md
@@ -2,7 +2,12 @@
 
 # Signing key
 
-Releases are signed with this key:
+Releases are signed with the GPG key of the individual who builds
+them.  Authorized keys will always be signed by key ID 0x575159689BEFB442,
+with the key and signature uploaded to the
+[SKS keyserver pool](https://sks-keyservers.net/).
+
+This is the public key block for 0x575159689BEFB442:
 
 ```
 -----BEGIN PGP PUBLIC KEY BLOCK-----
diff --git a/doc/azure_ci.md b/doc/azure_ci.md
--- a/doc/azure_ci.md
+++ b/doc/azure_ci.md
@@ -15,9 +15,7 @@
   [azure-simple](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-simple.yml)
   file into `azure-pipelines.yml`.
 * For complex Azure configuration, you need to take the below linked
-  four files and put all of them into the `.azure` directory except
-  the `azure-pipelines.yml` file which should be put in the root of
-  the repository.
+  four files and put all of them into the `.azure` directory.
 
 For a more detailed explanation, you can read further.
 
@@ -32,14 +30,9 @@
   with just the settings present in your `stack.yaml` file.
 * The complex Azure configuration is intended for projects that need
   to support multiple GHC versions and multiple OSes, such as open
-  source libraries to be released to Hackage. It tests against
-  cabal-install, as well as Stack on Linux and macOS. The
-  configuration is significantly more involved to allow for all of
-  this branching behavior. In the provided template, we use the Linux
-  build configuration to test against various combinations of
-  cabal-install and stack. The macOS and Windows configuration is used
-  only for testing Stack build configuration. These are the files for
-  the complex configuration:
+  source libraries to be released to Hackage. It tests against Stack
+  for different resolves on Linux, macOS and Windows.  These are the
+  files for the complex configuration:
   - [azure-pipelines.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-pipelines.yml) : This is the starter file used by the Azure CI.
   - [azure-linux-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-linux-template.yml) : Template for Azure Linux build
   - [azure-osx-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-osx-template.yml) : Template for Azure macOS build
@@ -102,19 +95,14 @@
 
 ``` yaml
 pool:
-  vmImage: ubuntu-16.04
+  vmImage: ubuntu-latest
 ```
 
-The other popular options are `macOS-10.13`, `vs2017-win2016` for Mac
+The other popular options are `macOS-latest`, `windows-latest` for Mac
 and Windows respectively. You can find the [complete
 list](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=vsts&tabs=yaml)
-here.
-
-Note that as of now, Azure CI doesn't offer any caching support. You
-can use something like [cache-s3](https://github.com/fpco/cache-s3)
-for explicit caching, although it may cost you. For a project with an
-example usage of `cache-s3`, you can see the Azure configuration of
-[stack](https://github.com/commercialhaskell/stack) repository.
+here. You also have the option to select a specific supported ubuntu
+version like `ubuntu-18.08`.
 
 ## Installing Stack
 
@@ -136,19 +124,7 @@
 - Install GHC using apt package manger. This method is only applicable
   for Debian based images.
 
-See the [simple azure
-script](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-simple.yml)
-for an example of the first option (letting Stack download GHC). Here,
-we will show the second option:
-
-```yaml
-sudo add-apt-repository -y ppa:hvr/ghc
-sudo apt-get update
-sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER
-```
-
-For the above commands to work, you need to set the `CABALVER` and
-`GHCVER` environment variable properly.
+But we only use the first method of using Stack to download GHC.
 
 ### Multiple GHC - parametrised builds
 
@@ -156,34 +132,22 @@
 `stack.yaml` files. If you don't want to put a specific `stack.yaml`
 for a particular resolver and still want to test it, you have specify
 your resolver argument in `ARGS` environment variable (you will see an
-example below). For cabal based builds, you have to specify both
-`GHCVER` and `CABALVER` environment variables.
-
+example below).
 ```
 strategy:
   matrix:
-    stack-def:
-      BUILD: stack
-      STACK_YAML: stack.yaml
-    stack-lts-13:
-      BUILD: stack
-      STACK_YAML: stack-lts-13.yaml
-    cabal-8.4.4:
-      BUILD: cabal
-      GHCVER: 8.4.4
-      CABALVER: 2.4
-    cabal-8.6.5:
-      BUILD: cabal
-      GHCVER: 8.6.5
-      CABALVER: 2.4
+    GHC 8.0:
+      ARGS: "--resolver lts-9"
+    GHC 8.2:
+      ARGS: "--resolver lts-11"
+    GHC 8.4:
+      ARGS: "--resolver lts-12"
+    GHC 8.6:
+      ARGS: "--resolver lts-14"
+    GHC 8.8:
+      ARGS: "--resolver lts-15"
     nightly:
-      BUILD: stack
       ARGS: "--resolver nightly"
-    style:
-      BUILD: style
-    pedantic:
-      BUILD: pedantic
-      STACK_YAML: stack.yaml
 ```
 
 ## Running tests
@@ -191,8 +155,7 @@
 After the environment setup, actual test running is simple:
 
 ```yaml
-script:
-  - stack test
+stack $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
 ```
 
 ## Other details
diff --git a/doc/build_command.md b/doc/build_command.md
--- a/doc/build_command.md
+++ b/doc/build_command.md
@@ -184,19 +184,22 @@
 
 ## Build output
 
-When building a single target package (e.g., `stack build` in a project with
-only one package, or `stack build package-name` in a multi-package project),
-the build output from GHC will be hidden for building all dependencies, and
-will be displayed for the one target package.
+Starting with Stack 2.1, output of all packages being built scrolls by in a
+streaming fashion. The output from each package built will be prefixed by the
+package name, e.g. `mtl> Building ...`. This will include the output from
+dependencies being built, not just targets.
 
-By default, when building multiple target packages, the output from these will
-end up in a log file instead of on the console unless it contains errors or
-warnings, to avoid problems of interleaved output and decrease console noise.
-If you would like to see this content instead, you can use the `--dump-logs`
-command line option, or add `dump-logs: all` to your `stack.yaml` file.
+To disable this behaviour, you can pass `--no-interleaved-output`, or add
+`interleaved-output: false` to your `stack.yaml` file.  When disabled:
 
-Alternatively, starting with Stack 1.8, you can pass `--interleaved-output` to
-see output of all packages being built scroll by in a streaming fashion. The
-output from each package built will be prefixed by the package name, e.g. `mtl>
-Building ...`. Note that, unlike the default output, this will include the
-output from dependencies being built, not just targets.
+  * When building a single target package (e.g., `stack build` in a project
+    with only one package, or `stack build package-name` in a multi-package
+    project), the build output from GHC will be hidden for building all
+    dependencies, and will be displayed for the one target package.
+
+  * By default, when building multiple target packages, the output from these
+    will end up in a log file instead of on the console unless it contains
+    errors or warnings, to avoid problems of interleaved output and decrease
+    console noise. If you would like to see this content instead, you can use
+    the `--dump-logs` command line option, or add `dump-logs: all` to your
+    `stack.yaml` file.
diff --git a/doc/coverage.md b/doc/coverage.md
--- a/doc/coverage.md
+++ b/doc/coverage.md
@@ -81,7 +81,7 @@
    the executable.
 
    When switching on this flag, it will usually cause all local packages to be
-   rebuilt (see [#1940](https://github.com/commercialhaskell/stack/issues/1940).
+   rebuilt (see [#1940](https://github.com/commercialhaskell/stack/issues/1940)).
 
 2. Before the build runs with `--coverage`, the contents of `stack path --local-hpc-root`
    gets deleted. This prevents old reports from getting mixed
diff --git a/doc/dependency_visualization.md b/doc/dependency_visualization.md
--- a/doc/dependency_visualization.md
+++ b/doc/dependency_visualization.md
@@ -5,6 +5,8 @@
 You can use stack to visualize the dependencies between your packages and
 optionally also external dependencies.
 
+First, you need [Graphviz](https://www.graphviz.org/). You can [get it here](https://www.graphviz.org/download/).
+
 As an example, let's look at `wreq`:
 
 ```
diff --git a/doc/developing_on_windows.md b/doc/developing_on_windows.md
--- a/doc/developing_on_windows.md
+++ b/doc/developing_on_windows.md
@@ -49,8 +49,8 @@
 installed with the commands:
 
 ```
-stack exec -- pacman -R mingw-w64-x86_64-make
-stack exec -- pacman -R mingw-w64-x86_64-cmake
+stack exec -- pacman -S mingw-w64-x86_64-make
+stack exec -- pacman -S mingw-w64-x86_64-cmake
 ```
 
 Even though make and cmake are then both installed into the same
diff --git a/doc/faq.md b/doc/faq.md
--- a/doc/faq.md
+++ b/doc/faq.md
@@ -47,8 +47,6 @@
 * Cabal-the-library is used by stack to build your Haskell code. See the
   [Architecture: Plan Execution](architecture.md#plan-execution) section for
   more detail, including how the Cabal version is chosen.
-* cabal-install (the executable) is used by stack for its dependency solver
-  functionality.
 * A .cabal file is provided for each package, and defines all package-level
   metadata just like it does in the cabal-install world: modules, executables,
   test suites, etc. No change at all on this front.
@@ -76,39 +74,35 @@
 
 ## I need to use a package (or version of a package) that is not available on hackage, what should I do?
 
-Add it to the `packages` list in your project's `stack.yaml`, specifying the
-package's source code location relative to the directory where your
-`stack.yaml` file lives, e.g.
+Add it to the 
+[`extra-deps`](yaml_configuration.md#extra-deps) list in your project's 
+`stack.yaml`, specifying the package's source code location relative to the 
+directory where your `stack.yaml` file lives, e.g.
 
 ```yaml
 resolver: lts-2.10
 packages:
 - '.'
+extra-deps:
 - third-party/proprietary-dep
 - github-version-of/conduit
 - patched/diagrams
-extra-deps: []
 ```
 
-The above example specifies that it should include the package at the root
-directory (`'.'`), that the `proprietary-dep` package is found in the project's
-`third-party` folder, that the `conduit` package is found in the project's
-`github-version-of` folder, and that the `diagrams` package is found in the
-project's `patched` folder. This autodetects changes and reinstalls the
+The above example specifies that the `proprietary-dep` package is found in the 
+project's `third-party` folder, that the `conduit` package is found in the 
+project's `github-version-of` folder, and that the `diagrams` package is found 
+in the project's `patched` folder. This autodetects changes and reinstalls the
 package.
 
 To install packages directly from a Git repository, use e.g.:
 
 ```yaml
-resolver: lts-2.10
-packages:
-- location:
-    git: https://github.com/githubuser/reponame.git
+extra-deps:
+  - git: https://github.com/githubuser/reponame.git
     commit: somecommitID
 ```
 
-Note that the `- '.'` line has been omitted, so the package in the root directory will not be used.
-
 ## What is the meaning of the arguments given to stack build, test, etc?
 
 Those are the targets of the build, and can have one of three formats:
@@ -129,13 +123,6 @@
 Another would be to add the upstream package as a submodule to your
 project.
 
-## Am I required to use a Stackage snapshot to use stack?
-
-No, not at all. If you prefer dependency solving to curation, you can continue
-with that workflow. Instead of describing the details of how that works here,
-it's probably easiest to just say: run `stack init --solver` and look at the
-generated stack.yaml.
-
 ## How do I use this with sandboxes?
 
 Explicit sandboxing on the part of the user is not required by stack. All
@@ -581,3 +568,19 @@
 **Note that we're fixing `ghc-8.2.2` in this case; repeat for other versions as necessary.** You should apply this fix for the version of GHC that matches your resolver.
 
 Issue [#4009](https://github.com/commercialhaskell/stack/issues/4009) on GitHub goes into further detail.
+
+## How do I install ghc in stack when it fails with the error: Missing ghc bindist for "linux64-ncurses6"?
+
+Example Error:
+```
+No setup information found for ghc-8.6.4 on your platform.
+This probably means a GHC bindist has not yet been added for OS key 'linux64-ncurses6'.
+Supported versions: ghc-7.10.3, ghc-8.0.1, ghc-8.0.2, ghc-8.2.1, ghc-8.2.2
+```
+
+Most Linux distributions have standardized on providing libtinfo.so.6 (either directly or as a symlink to libncursesw.so.6). As such, there aren't GHC 8.6.* bindists that link to libncursesw.so.6 available. 
+
+So creating a symlink to libncursesw.so.6 as libtinfo.so.6 can prevent this error (root privileges might be required).
+```
+ln -s /usr/lib/libncursesw.so.6 /usr/lib/libtinfo.so.6
+```
diff --git a/doc/ghcjs.md b/doc/ghcjs.md
--- a/doc/ghcjs.md
+++ b/doc/ghcjs.md
@@ -1,164 +1,5 @@
 <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div>
 
-# GHCJS (experimental)
-
-To use GHCJS with stack, place a GHCJS version in the [`compiler`](yaml_configuration.md#compiler) field of `stack.yaml`.  After this, some stack commands should work with GHCJS.  In particular:
-
-* `stack setup` will install GHCJS from source and boot it, which takes a long time.
-
-* `stack build` will compile your code to JavaScript.  In particular, the generated code for an executable ends up in `$(stack path --local-install-root)/bin/EXECUTABLE.jsexe/all.js` (bash syntax, where `EXECUTABLE` is the name of your executable).
-
-You can also build existing stack projects which target GHC, and instead build
-them with GHCJS.  For example: `stack build --compiler ghcjs-0.2.0.9006020_ghc-7.10.3`
-
-There are advanced options for `stack setup`: `--ghcjs-boot-options` (one word at a time) and `--[no-]ghcjs-boot-clean`
-which will pass your settings down to the `ghcjs-boot`. You will need to know exactly what you are doing with them.  
-
-Sidenote: If you receive a message like
-`The program 'ghcjs' version >=0.1 is required but the version of .../ghcjs could not be determined.`,
-then you may need to install a different version of `node`. See
-[issue #1496](https://github.com/commercialhaskell/stack/issues/1496).
-
-## Example Configurations
-
-### GHCJS repacked for snapsnots lts-8 and lts-9
-
-Please see the [ghcjs-stack-dist repository](https://github.com/matchwood/ghcjs-stack-dist) for `lts-8` and `lts-9` configurations and refer to the [README](https://github.com/matchwood/ghcjs-stack-dist/blob/master/README.md) for common issues.
-
-Support for `> lts-9` snapshots (`GHC 8.2` and above) is currently [work in progress](https://github.com/matchwood/ghcjs-stack-dist/issues/10).
-
-### GHCJS repacked for snapsnots < lts-8
-
-These versions of GHCJS were created by
-[Marcin Tolysz](https://github.com/tolysz), and were particularly crafted to
-include package versions which match those expected by particular stackage
-snapshots.
-
-For `ghcjs` based on `ghc-7.10.3` one could try:
-```yaml
-resolver: lts-6.30
-compiler: ghcjs-0.2.0.9006030_ghc-7.10.3
-compiler-check: match-exact
-
-setup-info:
-  ghcjs:
-    source:
-      ghcjs-0.2.0.9006030_ghc-7.10.3:
-         url: http://ghcjs.tolysz.org/lts-6.30-9006030.tar.gz
-         sha1: 2371e2ffe9e8781808b7a04313e6a0065b64ee51
-```
-
-Or for the latest one based on `ghc-8.0.1` (with more features):
-```yaml
-resolver: lts-7.19
-compiler: ghcjs-0.2.1.9007019_ghc-8.0.1
-compiler-check: match-exact
-
-setup-info:
-  ghcjs:
-    source:
-      ghcjs-0.2.1.9007019_ghc-8.0.1:
-           url: http://ghcjs.tolysz.org/ghc-8.0-2017-02-05-lts-7.19-9007019.tar.gz
-           sha1: d2cfc25f9cda32a25a87d9af68891b2186ee52f9
-```
-The latter can be generated via: https://github.com/tolysz/prepare-ghcjs
-the former is a bit more manual. Those bundles are only tested against the latest `node-7.4.0`.
-
-In order to correctly boot and use ghcjs, one might need to install `alex` `happy` `hscolour` `hsc2hs` with the normal ghc.
-
-Older resolvers:
-
-|resolver|ghcjs|url|sha1|
-|---|---|---|---|
-| lts-7.19 |0.2.1| http://ghcjs.tolysz.org/ghc-8.0-2017-02-05-lts-7.19-9007019.tar.gz | d2cfc25f9cda32a25a87d9af68891b2186ee52f9 |
-| lts-7.15 |0.2.1| http://ghcjs.tolysz.org/ghc-8.0-2017-01-11-lts-7.15-9007015.tar.gz | 30d34e9d704bdb799066387dfa1ba98b8884d932 |
-| lts-7.14 |0.2.1| http://ghcjs.tolysz.org/ghc-8.0-2016-12-25-lts-7.14-9007014.tar.gz | 530c4ee5e19e2874e128431c7ad421e336df0303 |
-| lts-7.13 |0.2.1| http://ghcjs.tolysz.org/ghc-8.0-2016-12-18-lts-7.13-9007013.tar.gz | 0d2ebe0931b29adca7cb9d9b9f77d60095bfb864 |
-| lts-7.8 || http://ghcjs.tolysz.org/ghc-8.0-2016-11-07-lts-7.8-9007008.tar.gz | 190300a3725cde44b2a08be9ef829f2077bf8825 |
-| lts-7.7 || http://ghcjs.tolysz.org/ghc-8.0-2016-11-03-lts-7.7-9007007.tar.gz | ce169f85f1c49ad613ae77fc494d5565452ff59a |
-| lts-7.5 || http://ghcjs.tolysz.org/ghc-8.0-2016-10-24-lts-7.5-9007005.tar.gz | 450e81028d7f1eb82a16bc4b0809f30730c3e173 |
-| lts-7.4 || http://ghcjs.tolysz.org/ghc-8.0-2016-10-22-lts-7.4-9007004.tar.gz | ed77b3c15fedbadad5ab0e0afe1bd42c0a8695b4 |
-| lts-7.3 || http://ghcjs.tolysz.org/ghc-8.0-2016-10-11-lts-7.3-9007003.tar.gz | 3196fd5eaed670416083cf3678396d02c50096de |
-| lts-7.2 || http://ghcjs.tolysz.org/ghc-8.0-2016-10-01-lts-7.2-9007002.tar.gz | a41ae415328e2b257d40724d13d1386390c26322 | 
-| lts-7.1 || http://ghcjs.tolysz.org/ghc-8.0-2016-09-26-lts-7.1-9007001-mem.tar.gz | e640724883238593e2d2f7f03991cb413ec0347b |
-| lts-6.25 | 0.2.0 | http://ghcjs.tolysz.org/lts-6.25-9006025.tar.gz | 3c87228579b55c05e227a7876682c2a7d4c9c007 |
-| lts-6.21 || http://ghcjs.tolysz.org/lts-6.21-9006021.tar.gz | 80b83f85dcec182093418e843979f4cee092fa85 |
-| lts-6.20 || http://ghcjs.tolysz.org/lts-6.20-9006020.tar.gz | a6cea90cd8121eee3afb201183c6e9bd6bacd94a |
-| lts-6.19 || http://ghcjs.tolysz.org/lts-6.19-9006019.tar.gz | ef4264d5a93b269ee4ec8f9d5139da030331d65a |
-| lts-6.18 || http://ghcjs.tolysz.org/lts-6.18-9006018.tar.gz | 3e9f345116c851349a5a551ffd94f7e0b74bfabb |
-
-If you do not use the same resolver, say, an older LTS snapshot, you will get
-some warnings like this:
-
-```
-Ignoring that the GHCJS boot package "aeson" has a different version, 0.9.0.1, than the resolver's wanted version, 0.8.0.2
-Ignoring that the GHCJS boot package "attoparsec" has a different version, 0.13.0.1, than the resolver's wanted version, 0.12.1.6
-Ignoring that the GHCJS boot package "scientific" has a different version, 0.3.3.8, than the resolver's wanted version, 0.3.4.2
-...
-```
-
-These warnings can usually be safely ignored, but they do indicate a divergence
-between your snapshot's packages, and those that are being used to compile your
-project. You will normally get these warnings when using a GHCJS tarball that
-has not been packaged with a particular snapshot in mind.
-
-### GHCJS (old base)
-
-If you want to build some older GHCJS packages, you may need to use the "old
-base" GHCJS.  To do this, use the following compiler info:
-
-```yaml
-compiler: ghcjs-0.1.0.20150924_ghc-7.10.2
-compiler-check: match-exact
-```
-
-### Custom installed GHCJS
-
-In order to use a GHCJS installed on your PATH, just add the following to your `stack.yaml`:
-
-```yaml
-compiler: ghcjs-0.2.0_ghc-7.10.2
-```
-
-(Or, `ghcjs-0.1.0_ghc-7.10.2` if you are working with an older version)
-
-This is particularly useful when you have built GHCJS from source.
-
-## Project with both client and server
-
-For projects with both a server and client, the recommended project
-organization is to put one or both of your `stack.yaml` files in
-sub-directories.  This way, you can use the current working directory to
-specify whether you're working on the client or server.  This will also allow
-more straightforward editor tooling, once projects like `ghc-mod` and
-`haskell-ide-engine` support GHCJS.
-
-For example, here's what a script for building both client and server looks
-like:
-
-```bash
-#!/bin/bash
-
-# Build the client
-stack build --stack-yaml=client/stack.yaml
-
-# Copy over the javascript
-rm -f server/static/all.js
-cp $(stack path --stack-yaml=client/stack.yaml --local-install-root)/bin/client.jsexe/all.js server/static/all.js
-
-# Build the server
-stack build --stack-yaml=server/stack.yaml
-```
-
-You can also put both the yaml files in the same directory, and have e.g.
-`ghcjs-stack.yaml`, but this won't work well with editor integrations.
-
-## Using stack without a snapshot
-
-If you don't want to use a snapshot, instead place the ghcjs version in the `resolver` field of your `stack.yaml`.  This is also necessary when using stack `< 0.1.8`.
-
-## Setting up GHCJS on Windows
+# GHCJS (removed)
 
-If `stack setup` command fails to successfully complete with message: `commitBuffer: invalid argument (invalid character)`, it means you have a locale problem.
-This problem is not exclusive to GHCJS, and might happen also during other builds. A workaround is to set _Language for non-Unicode programs_ to _English (US)_.
-For details see [stack issue #1448](https://github.com/commercialhaskell/stack/issues/1448).
+GHCJS support is no longer included in Stack as of version 2.3.
diff --git a/doc/install_and_upgrade.md b/doc/install_and_upgrade.md
--- a/doc/install_and_upgrade.md
+++ b/doc/install_and_upgrade.md
@@ -32,7 +32,6 @@
 will make `stack install` and `stack upgrade` work correctly out of the box.
 
   * [Windows 64-bit Installer](https://get.haskellstack.org/stable/windows-x86_64-installer.exe)
-  * [Windows 32-bit Installer](https://get.haskellstack.org/stable/windows-i386-installer.exe)
 
 If in doubt: you should prefer the 64-bit installer.
 
@@ -45,7 +44,6 @@
 * Download the latest release:
 
     * [Windows 64-bit](https://get.haskellstack.org/stable/windows-x86_64.zip)
-    * [Windows 32-bit](https://get.haskellstack.org/stable/windows-i386.zip)
 
 * 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.
@@ -141,8 +139,8 @@
 
 There is also an
 unofficial
-[Fedora Copr repo](https://copr.fedoraproject.org/coprs/petersen/stack/) which
-can be enabled with: `sudo dnf copr enable petersen/stack`. Note that this Stack
+[Fedora Copr repo](https://copr.fedoraproject.org/coprs/petersen/stack2/) which
+can be enabled with: `sudo dnf copr enable petersen/stack2`. Note that this Stack
 version may lag behind, so we recommend running `stack upgrade` after installing
 it.
 
@@ -244,7 +242,7 @@
       (note: requires libgmp.so.10, and will not work on some older
       distributions that have libgmp.so.3, such as CentOS 6)
 
-    * [Linux ARMv7](https://get.haskellstack.org/stable/linux-arm.tar.gz)
+    <!-- * [Linux ARMv7](https://get.haskellstack.org/stable/linux-arm.tar.gz) -->
 
     * [Linux AArch64](https://get.haskellstack.org/stable/linux-aarch64.tar.gz)
 
@@ -313,21 +311,32 @@
 
 If you're attempting to install stack from within China:
 
-* As of 2018-10-24, the download link has limited connectivity from within mainland China. If this is the case, please proceed by manually downloading (ideally via a VPN) and installing stack per the instructions found on this page pertinent to your OS.
+* As of 2020-02-24, the download link has limited connectivity from within mainland China. If this is the case, please proceed by manually downloading (ideally via a VPN) and installing stack per the instructions found on this page pertinent to your OS.
 
 * After install, your ~/.stack/config.yaml will need to be configured before stack can download large files consistently from within China (without reliance on a VPN). Please add the following to the bottom of the ~/.stack/config.yaml file (for Windows: use the %STACK_ROOT%\config.yaml):
 
 ```
 ###ADD THIS IF YOU LIVE IN CHINA
-setup-info: "http://mirrors.tuna.tsinghua.edu.cn/stackage/stack-setup.yaml"
+setup-info-locations: 
+- "http://mirrors.tuna.tsinghua.edu.cn/stackage/stack-setup.yaml"
 urls:
   latest-snapshot: http://mirrors.tuna.tsinghua.edu.cn/stackage/snapshots.json
-  lts-build-plans: http://mirrors.tuna.tsinghua.edu.cn/stackage/lts-haskell/
-  nightly-build-plans: http://mirrors.tuna.tsinghua.edu.cn/stackage/stackage-nightly/
+
 package-indices:
- - name: Tsinghua
-   download-prefix: http://mirrors.tuna.tsinghua.edu.cn/hackage/package/
-   http: http://mirrors.tuna.tsinghua.edu.cn/hackage/00-index.tar.gz
+  - download-prefix: http://mirrors.tuna.tsinghua.edu.cn/hackage/
+    hackage-security:
+        keyids:
+        - 0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d
+        - 1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42
+        - 280b10153a522681163658cb49f632cde3f38d768b736ddbc901d99a1a772833
+        - 2a96b1889dc221c17296fcc2bb34b908ca9734376f0f361660200935916ef201
+        - 2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3
+        - 51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921
+        - 772e9f4c7db33d251d5c6e357199c819e569d130857dc225549b40845ff0890d
+        - aa315286e6ad281ad61182235533c41e806e5a787e0b6d1e7eef3f09d137d2e9
+        - fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0
+        key-threshold: 3
+        ignore-expiry: no
 ```
 
 ## Using an http proxy
@@ -358,3 +367,25 @@
       wget -qO- https://get.haskellstack.org/ | sh -s - -f
 
 * Manually follow the steps above to download the newest binaries from the release page and replace the old binary.
+
+## Install Older Versions
+
+To install a specific version of stack, navigate to the desired version on 
+[the GitHub release page](https://github.com/fpco/stack/releases),
+and click the appropriate link under its "Assets" drop-down menu.
+
+Alternatively, use the URL 
+`https://github.com/commercialhaskell/stack/releases/download/vVERSION/stack-VERSION-PLATFORM.EXTENSION`.
+For example, the tarball for stack 2.1.0.1, osx-x86_64 is at
+`https://github.com/commercialhaskell/stack/releases/download/v2.1.0.1/stack-2.1.0.1-osx-x86_64.tar.gz`.
+
+Here's a snippet for `appveyor.yml` files, borrowed from `dhall`'s 
+[`appveyor.yml`](https://github.com/dhall-lang/dhall-haskell/blob/1079b7a3a7a6922f72a373e47daf6f1b74f128b1/appveyor.yml).
+Change the values of PATH and VERSION as needed.
+
+    install:
+      - set PATH=C:\Program Files\Git\mingw64\bin;%PATH%
+      - curl --silent --show-error --output stack.zip --location "https://github.com/commercialhaskell/stack/releases/download/v%STACK_VERSION%/stack-%STACK_VERSION%-windows-x86_64.zip"
+      - 7z x stack.zip stack.exe
+      - stack setup > nul
+      - git submodule update --init --recursive
diff --git a/doc/lock_files.md b/doc/lock_files.md
--- a/doc/lock_files.md
+++ b/doc/lock_files.md
@@ -67,9 +67,6 @@
 extra-deps:
 - size: 1442
   url: https://hackage.haskell.org/package/acme-missiles-0.3.tar.gz
-  cabal-file:
-    size: 613
-    sha256: 2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1
   name: acme-missiles
   version: '0.3'
   sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b
@@ -150,9 +147,6 @@
   completed:
     size: 1442
     url: https://hackage.haskell.org/package/acme-missiles-0.3.tar.gz
-    cabal-file:
-      size: 613
-      sha256: 2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1
     name: acme-missiles
     version: '0.3'
     sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b
diff --git a/doc/nix_integration.md b/doc/nix_integration.md
--- a/doc/nix_integration.md
+++ b/doc/nix_integration.md
@@ -86,12 +86,11 @@
 $ nix-instantiate --eval -E "with import <nixpkgs> {}; lib.attrNames haskell.compiler"
 ```
 
-Alternatively, install `nix-repl`, a convenient tool to explore
+Alternatively, use `nix repl`, a convenient tool to explore
 nixpkgs:
 
 ```sh
-$ nix-env -i nix-repl
-$ nix-repl
+$ nix repl
 ```
 
 In the REPL, load nixpkgs and get the same information through
@@ -102,7 +101,7 @@
 nix-repl> haskell.compiler.ghc<Tab>
 ```
 
-You can type and evaluate any nix expression in the nix-repl, such as
+You can type and evaluate any nix expression in the nix repl, such as
 the one we gave to `nix-instantiate` earlier.
 
 **Note:** currently, stack only discovers dynamic and static libraries
diff --git a/doc/nonstandard_project_init.md b/doc/nonstandard_project_init.md
--- a/doc/nonstandard_project_init.md
+++ b/doc/nonstandard_project_init.md
@@ -18,7 +18,7 @@
 packages.
 
 ### Issues Referenced
-  - https://github.com/commercialhaskell/stack/issues/105
+  - <https://github.com/commercialhaskell/stack/issues/105>
 
 ## Passing Flags to Cabal
 
@@ -50,12 +50,12 @@
 
 
 ### Issues Referenced
-  - https://github.com/commercialhaskell/stack/issues/191
-  - https://github.com/commercialhaskell/stack/issues/417
-  - https://github.com/commercialhaskell/stack/issues/335
-  - https://github.com/commercialhaskell/stack/issues/301
-  - https://github.com/commercialhaskell/stack/issues/365
-  - https://github.com/commercialhaskell/stack/issues/105
+  - <https://github.com/commercialhaskell/stack/issues/191>
+  - <https://github.com/commercialhaskell/stack/issues/417>
+  - <https://github.com/commercialhaskell/stack/issues/335>
+  - <https://github.com/commercialhaskell/stack/issues/301>
+  - <https://github.com/commercialhaskell/stack/issues/365>
+  - <https://github.com/commercialhaskell/stack/issues/105>
 
 ## Selecting a Resolver
 
@@ -75,8 +75,8 @@
 :TODO: Document `--solver`
 
 ### Issues Referenced
-  - https://github.com/commercialhaskell/stack/issues/468
-  - https://github.com/commercialhaskell/stack/issues/464
+  - <https://github.com/commercialhaskell/stack/issues/468>
+  - <https://github.com/commercialhaskell/stack/issues/464>
 
 ## Using git Repositories
 
@@ -86,8 +86,8 @@
 information.
 
 ### Issues Referenced
-  - https://github.com/commercialhaskell/stack/issues/254
-  - https://github.com/commercialhaskell/stack/issues/199
+  - <https://github.com/commercialhaskell/stack/issues/254>
+  - <https://github.com/commercialhaskell/stack/issues/199>
 
 ## Private Hackage
 Working with a private Hackage is currently supported in certain situations.
@@ -105,16 +105,16 @@
 For further information see [YAML configuration](yaml_configuration.md)
 
 ### Issues Referenced
-  - https://github.com/commercialhaskell/stack/issues/445
-  - https://github.com/commercialhaskell/stack/issues/565
+  - <https://github.com/commercialhaskell/stack/issues/445>
+  - <https://github.com/commercialhaskell/stack/issues/565>
 
 ## Custom Snapshots
 See [Custom Snapshots](custom_snapshot.md).
 
 ### Issues Referenced
-  - https://github.com/commercialhaskell/stack/issues/111
-  - https://github.com/commercialhaskell/stack/issues/253
-  - https://github.com/commercialhaskell/stack/issues/137
+  - <https://github.com/commercialhaskell/stack/issues/111>
+  - <https://github.com/commercialhaskell/stack/issues/253>
+  - <https://github.com/commercialhaskell/stack/issues/137>
 
 ## Intra-package Targets
 Stack supports intra-package targets, similar to `cabal build COMPONENTS` for
@@ -129,4 +129,4 @@
 Note: this does require prefixing the component name with the package name.
 
 ### Issues referenced
-  - https://github.com/commercialhaskell/stack/issues/201
+  - <https://github.com/commercialhaskell/stack/issues/201>
diff --git a/doc/pantry.md b/doc/pantry.md
--- a/doc/pantry.md
+++ b/doc/pantry.md
@@ -13,23 +13,6 @@
 * Package location specification (in the `extra-deps` field and inside snapshots)
 * Snapshot specification, for creating custom snapshots
 
-## Freeze command
-
-As you'll see throughout this document, there is a lot of additional
-information that can be provided to Stack to make the configuration
-more reproducible and faster to parse. However, it's tedious to
-specify these values manually. Therefore, the recommended workflow is:
-
-* Manually write the simple version of a configuration value
-* Use `stack freeze` to obtain the more reproducible version
-
-The standard `stack freeze` will operate on your `stack.yaml` file, and provide
-you with updated `resolver` and `extra-deps` values, if relevant. If you run
-`stack freeze --snapshot`, it will provide you with an update snapshot file.
-
-New contents will be printed to `stdout` instead of modifying your existing
-files to avoid mutation of user-created files.
-
 ## Snapshot location
 
 There are essentially four different ways of specifying a snapshot
@@ -55,9 +38,9 @@
   sha256: 781ea577595dff08b9c8794761ba1321020e3e1ec3297fb833fe951cce1bee11
 ```
 
-Where the `size` is the number of bytes in the file, and `sha256` is
-its SHA256 hash. This information can automatically be generated with
-the [`stack freeze`](#freeze-command) command.
+Where the `size` is the number of bytes in the file, and `sha256` is its SHA256
+hash. If not provided, the information will automatically be generated and
+stored in a lock file.
 
 ## Package location
 
@@ -69,8 +52,7 @@
 
 All three of these formats support optional tree metadata to be added,
 which can be used for reproducibility and faster downloads. This
-information can automatically be generated with the [`stack
-freeze`](#freeze-command) command.
+information can automatically be generated in a lock file.
 
 ### Hackage
 
@@ -111,7 +93,7 @@
 equally reproducible build plans.
 
 Finally, you can include the Pantry tree information. The following
-was generated with `stack freeze`:
+would be generated and stored in the lock file:
 
 ```yaml
 - hackage: acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,613
@@ -172,48 +154,6 @@
 explicitly specified if a required package is found in the top-level
 directory of the repository.
 
-Using the `stack freeze` command will add in additional information,
-including not only the Pantry tree hash, but also package metadata
-which can allow Stack to work faster by bypassing cabal file
-parses. For example, this:
-
-```yaml
-extra-deps:
-- git: git@github.com:yesodweb/wai
-  commit: 2f8a8e1b771829f4a8a77c0111352ce45a14c30f
-  subdirs:
-  - auto-update
-  - wai
-```
-
-Would be converted into:
-
-```yaml
-extra-deps:
-- subdir: auto-update
-  cabal-file:
-    size: 1219
-    sha256: c07b2b1a2df1199f83eef819ac9bb067567e100b60586a52f8b92fc733ae3a6d
-  name: auto-update
-  version: 0.1.2.1
-  git: git@github.com:yesodweb/wai
-  pantry-tree:
-    size: 687
-    sha256: 26377897f35ccd3890b4405d72523233717afb04d62f2d36031bf6b18dcef74f
-  commit: 2f8a8e1b771829f4a8a77c0111352ce45a14c30f
-- subdir: wai
-  cabal-file:
-    size: 1717
-    sha256: 7b46e7a8b121d668351fa8a684810afadf58c39276125098485203ef274fd056
-  name: wai
-  version: 3.0.2.3
-  git: git@github.com:yesodweb/wai
-  pantry-tree:
-    size: 10299
-    sha256: ce33fddab13592c847fbd7acd1859dfcbb9aeb6c212db3cee27c909fa3f3ae44
-  commit: 2f8a8e1b771829f4a8a77c0111352ce45a14c30f
-```
-
 #### Limited [git-annex](https://git-annex.branchable.com) support
 
 Pantry does not support [git-annex](https://git-annex.branchable.com). This is
@@ -254,58 +194,6 @@
   sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b
 ```
 
-With the `stack freeze` command, this would be replaced with:
-
-```yaml
-extra-deps:
-- size: 1540
-  url: https://hackage.haskell.org/package/acme-dont-1.1.tar.gz
-  cabal-file:
-    size: 602
-    sha256: 8264ad3e5113d3e0417b46e71d5a9c0914a1f03b5b81319cc329f1dc0f49b96c
-  name: acme-dont
-  version: '1.1'
-  sha256: c32231ff8548bccd4f3bafcc9b1eb84947a2e5e0897c50c048e0e7609fc443ce
-  pantry-tree:
-    size: 206
-    sha256: 79dbeddaf0fd507611687cefe9511c8fda489849fb0cac3894925716936290b2
-- size: 285152
-  subdir: wai
-  url: http://github.com/yesodweb/wai/archive/2f8a8e1b771829f4a8a77c0111352ce45a14c30f.zip
-  cabal-file:
-    size: 1717
-    sha256: 7b46e7a8b121d668351fa8a684810afadf58c39276125098485203ef274fd056
-  name: wai
-  version: 3.0.2.3
-  sha256: 3b6eb04f3763ca16432f3ab2135d239161fbe2c8811b8cd1778ffa67469289ba
-  pantry-tree:
-    size: 10296
-    sha256: ce431f1a22fcda89375ba5e35e53aee968eea23d1124fcba7cb9eae426daa2db
-- size: 285152
-  subdir: warp
-  url: http://github.com/yesodweb/wai/archive/2f8a8e1b771829f4a8a77c0111352ce45a14c30f.zip
-  cabal-file:
-    size: 6648
-    sha256: e3f01fd7417af923fd30962e9e6a4fe4de41ebc5e02af9819067fed79c9c6575
-  name: warp
-  version: 3.0.13.1
-  sha256: 3b6eb04f3763ca16432f3ab2135d239161fbe2c8811b8cd1778ffa67469289ba
-  pantry-tree:
-    size: 4292
-    sha256: d6b1def306a042b5fc500930302533a3ea828e916c99cbd82c0b7e2c4e3a8e09
-- size: 1442
-  filepath: acme-missiles-0.3.tar.gz
-  cabal-file:
-    size: 613
-    sha256: 2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1
-  name: acme-missiles
-  version: '0.3'
-  sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b
-  pantry-tree:
-    size: 226
-    sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033
-```
-
 ## Snapshots
 
 _NOTE_ Stack has supported custom snapshots properly since version
@@ -366,41 +254,6 @@
 identify the snapshot internally. It is often reasonably efficient to modify a
 custom snapshot, due to stack sharing snapshot packages whenever possible.
 
-Running the `stack freeze --snapshot` command yields the following
-output:
-
-```yaml
-flags:
-  unordered-containers:
-    debug: true
-ghc-options:
-  warp:
-  - -O2
-packages:
-- hackage: unordered-containers-0.2.7.1@sha256:7a1ceb6d88c0f16ec417f28dac16f6dc7b10e88fbb536a74d84941ad2f57b74b,4367
-  pantry-tree:
-    size: 1286
-    sha256: 8a8f745cacae3c11a9c6e6c2fcefc95a13d0c153a8e14b4d28485db1b59d9ef3
-- hackage: hashable-1.2.4.0@sha256:33a49b3ea87cc4a0c89a4fd48f19e4807d8c620aff710a048a28cf7d9c9b4620,4271
-  pantry-tree:
-    size: 1325
-    sha256: cb05c31a8ec43f727004e5a6c8e35ff92e0515855a85cb01fa73623683ee4b33
-- hackage: text-1.2.2.1@sha256:1c6ffad395d1674915cc9fda1d3b8f202ddcbfda7c341eb8bd99de67d3283bf9,5724
-  pantry-tree:
-    size: 7376
-    sha256: ac2601c49cf7bc0f5d66b2793eddc8352f51a6ee989980827a0d0d8169700a03
-hidden:
-  warp: false
-  wai: true
-drop-packages:
-- wai-extra
-compiler: ghc-8.0.1
-resolver:
-  size: 515969
-  url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/8/21.yaml
-  sha256: 2ec73d520d3e55cb753eaca11a72a9ce95bd9ba7ccaf16de1150d0130a50a5a1
-```
-
 ### Overriding the compiler
 
 The following snapshot specification will be identical to `lts-7.1`, but instead
@@ -462,13 +315,3 @@
   text:
     developer: true
 ```
-
-## Updating frozen information
-
-Suppose you're depending on `foo-1.2.3` from Hackage, and have used `stack
-freeze` on your file. Now you'd like to upgrade to `foo-1.2.4`. Doing so
-requires you to:
-
-* Change the version number specified to `1.2.4`
-* Remove any freeze information that may conflict, like cabal file info, pantry tree, etc
-* Rerun the `stack freeze` command to generate the new freeze information
diff --git a/doc/stack_yaml_vs_cabal_package_file.md b/doc/stack_yaml_vs_cabal_package_file.md
--- a/doc/stack_yaml_vs_cabal_package_file.md
+++ b/doc/stack_yaml_vs_cabal_package_file.md
@@ -104,7 +104,7 @@
 the interim, the build plan generated should be the same.
 
 \* There's at least one hole in this theory today, which is Hackage revisions.
-When you specify `extra-deps: [acme-missiles-0.3]`, it doesnt' specify which
+When you specify `extra-deps: [acme-missiles-0.3]`, it doesn't specify which
 revision of the cabal file to use, and Stack will just choose the latest. Stack
 version 1.6 added the ability to specify exact revisions of cabal files, but
 this isn't enforced as a requirement as it's so different from the way most
@@ -134,3 +134,7 @@
 need to add it explicitly to your `stack.yaml` file: it's already there
 implicitly via the `resolver` setting. This is what you do the majority of the
 time, such as when you add `vector` or `mtl` as a `build-depends` value.
+
+## Should I check in generated cabal files?
+
+Yes, you should. This recommendation was changed in [issue #5210](https://github.com/commercialhaskell/stack/issues/5210), please see the discussion there.
diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md
--- a/doc/yaml_configuration.md
+++ b/doc/yaml_configuration.md
@@ -61,7 +61,6 @@
 * Stackage Nightly snapshot, e.g. `resolver: nightly-2015-06-16`
 * No snapshot, just use packages shipped with the compiler
     * For GHC this looks like `resolver: ghc-7.10.2`
-    * For GHCJS this looks like `resolver: ghcjs-0.1.0_ghc-7.10.2`.
 * Custom snapshot, via a URL or relative file path. (See [pantry docs](pantry.md) for more information.)
 
 Each of these resolvers will also determine what constraints are placed on the
@@ -345,8 +344,8 @@
 snapshots failing to work.
 
 Note: since Stack v2.1.3, `ignore-expiry` was changed to `true` by
-default. For more information on this change, see [issue
-#4928](https://github.com/commercialhaskell/stack/issues/4928).
+default. For more information on this change, see
+[issue #4928](https://github.com/commercialhaskell/stack/issues/4928).
 
 ### system-ghc
 
@@ -443,14 +442,12 @@
 
 Overrides the compiler version in the resolver. Note that the `compiler-check`
 flag also applies to the version numbers. This uses the same syntax as compiler
-resolvers like `ghc-7.10.2` or `ghcjs-0.1.0.20150924_ghc-7.10.2` (version used
-for the 'old-base' version of GHCJS).  While it's useful to override the
-compiler for a variety of reasons, the main usecase is to use GHCJS with a
-stackage snapshot, like this:
+resolvers like `ghc-8.6.5`. This can be used to override the
+compiler for a Stackage snapshot, like this:
 
 ```yaml
-resolver: lts-3.10
-compiler: ghcjs-0.1.0.20150924_ghc-7.10.2
+resolver: lts-14.20
+compiler: ghc-8.6.4
 compiler-check: match-exact
 ```
 
@@ -617,8 +614,9 @@
 * `integersimple`: Use a GHC bindist that uses
   [integer-simple instead of GMP](https://ghc.haskell.org/trac/ghc/wiki/ReplacingGMPNotes)
 * any other value: Use a custom GHC bindist. You should specify
-  [setup-info](#setup-info) so `stack setup` knows where to download it, or
-  pass the `stack setup --ghc-bindist` argument on the command-line
+  [setup-info](#setup-info) or [setup-info-locations](#setup-info-locations) 
+  so `stack setup` knows where to download it,
+  or pass the `stack setup --ghc-bindist` argument on the command-line
 
 This option is incompatible with `system-ghc: true`.
 
@@ -630,14 +628,92 @@
 determined automatically, but you can override the autodetected value here.
 Possible arguments include `standard`, `gmp4`, `tinfo6`, and `nopie`.
 
+### setup-info-locations
+
+(Since 2.3)
+
+Possible usages of this config are:
+1. Using `stack` offline or behind a firewall
+2. Extending the tools known to `stack` such as cutting-edge versions of `ghc` or builds for custom linux distributions.
+
+The `setup-info` dictionary specifies locations for installation of Haskell-related tooling - it maps `(Tool, Platform, Version)` to the location where it can be obtained, such as `(GHC, Windows64, 8.6.5)` to the url hosting the `*.tar.xz` for GHC's installation.
+
+By default, it's obtained from [stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml).
+
+The `setup-info` dictionary is constructed in the following order:
+1. `setup-info` yaml configuration - inline config
+2. `--setup-info-yaml` command line arguments - urls or paths, multiple locations may be specified.
+3. `setup-info-locations` yaml configuration - urls or paths
+
+The first location which specifies the location of a tool `(Tool, Platform, Version)` takes precedence, so one can extend the default tools with a fallback to the default `setup-info` location:
+
+```yaml
+setup-info-locations:
+- C:/stack-offline/my-stack-setup.yaml
+- relative/inside/my/project/setup-info.yaml
+- \\smbShare\stack\my-stack-setup.yaml
+- http://stack-mirror.com/stack-setup.yaml
+- https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml
+```
+
+The default `setup-info` location is included only if no locations in the `setup-info-locations` config or the  `--setup-info-yaml` command line argument were specified.
+
+Thus the following will cause `stack setup` not to consult github for the `setup-info`:
+```yaml
+setup-info-locations:
+- C:/stack-offline/my-stack-setup.yaml
+```
+
+```yaml
+setup-info-locations: []
+```
+
+Relative paths are resolved relative to the `stack.yaml` file - either in the local project or the global `stack.yaml` in the stack directory.
+
+Relative paths may also be used inside paths to tool installs - such as for ghc or 7z, which allows vendoring the tools inside a monorepo.
+For example:
+
+Directory structure:
+```
+- src/
+- installs/
+  - my-stack-setup.yaml
+  - 7z.exe
+  - 7z.dll
+  - ghc-8.2.2.tar.xz
+- stack.yaml
+```
+
+In the project's `stack.yaml`:
+```yaml
+setup-info-locations:
+- installs/my-stack-setup.yaml
+```
+
+In `installs/my-stack-setup.yaml`:
+```yaml
+sevenzexe-info:
+    url: "installs/7z.exe"
+
+sevenzdll-info:
+    url: "installs/7z.dll"
+
+ghc:
+    windows64:
+        8.2.2:
+            url: "installs/ghc-8.2.2.tar.xz"
+```
+
 ### setup-info
 
 (Since 0.1.5)
 
 Allows augmenting from where tools like GHC and msys2 (on Windows) are
 downloaded. Most useful for specifying locations of custom GHC binary
-distributions (for use with the [ghc-variant](#ghc-variant) option):
+distributions (for use with the [ghc-variant](#ghc-variant) option).
 
+The format of this field is the same as in the default [stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml):
+
 ```yaml
 setup-info:
   ghc:
@@ -646,18 +722,14 @@
         url: "https://example.com/ghc-7.10.2-i386-unknown-mingw32-foo.tar.xz"
 ```
 
-Or you can point to external setup-info:
+This configuration **adds** the specified setup info metadata to the default;
+Specifying this config **does not** prevent the default `stack-setup-2.yaml` from being consulted as a fallback.
 
+If you need to **replace** the default setup-info, add the following:
+
 ```yaml
-setup-info: "https://example.com/my-stack-setup-info.yaml"
+setup-info-locations: []
 ```
-
-This may be either URL or (since 1.2.0) absolute file path.
-
-Note that this **adds** the specified setup info metadata to the default.
-If you need to **replace** it, use the `stack --setup-info-yaml` command-line
-argument instead.  The default setup metadata is in
-[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml).
 
 ### pvp-bounds
 
diff --git a/snapshot.yaml b/snapshot.yaml
deleted file mode 100644
--- a/snapshot.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-resolver: lts-11.22
-name: snapshot-for-building-stack-with-ghc-8.2.2
-
-packages:
-- ansi-terminal-0.9@rev:0
-- Cabal-2.4.0.1@rev:0
-- infer-license-0.2.0@rev:0 #for hpack-0.31
-- hpack-0.31.2@rev:0
-- githash-0.1.3.0@rev:0
-- rio-orphans-0.1.1.0@sha256:15600084c56ef4e1f22ac2091d10fa6ed62f01f531d819c6a5a19492212a76c9
-- yaml-0.10.4.0@rev:0 #for hpack-0.31
-- tar-conduit-0.3.0@sha256:c220b7a74b986445d08706aed77f17f82807d0133a5f3a760f53d587d20865b2,2928
-- hackage-security-0.5.3.0@rev:2
-- http-api-data-0.3.8.1@rev:1
-- cabal-doctest-1.0.6@rev:2
-- unliftio-0.2.12@rev:0 #for rio-0.1.11.0
-- happy-1.19.9@sha256:f8c774230735a390c287b2980cfcd2703d24d8dde85a01ea721b7b4b4c82944f,4667
-- fsnotify-0.3.0.1@rev:1
-- process-1.6.3.0@sha256:fc77cfe75a9653b8c54ae455ead8c06cb8adc4d7a340984d84d8ca880b579919,2370 #because of https://github.com/haskell/process/pull/101
-- persistent-2.9.2@rev:0
-- persistent-sqlite-2.9.3@rev:0
-- rio-0.1.11.0@rev:0
-- ansi-wl-pprint-0.6.8.2@rev:1 # for ansi-terminal-0.9
-- hedgehog-0.6.1@rev:4 # for ansi-terminal-0.9
-- typed-process-0.2.6.0@rev:0 # for rio-0.1.10.0
-- rio-prettyprint-0.1.0.0
-- hi-file-parser-0.1.0.0
-- http-download-0.1.0.0
-- pantry-0.1.1.1
-- git: https://github.com/snoyberg/filelock.git
-  commit: 97e83ecc133cd60a99df8e1fa5a3c2739ad007dc
-
-drop-packages:
-# See https://github.com/commercialhaskell/stack/pull/4712
-- cabal-install
diff --git a/src/Data/Attoparsec/Interpreter.hs b/src/Data/Attoparsec/Interpreter.hs
--- a/src/Data/Attoparsec/Interpreter.hs
+++ b/src/Data/Attoparsec/Interpreter.hs
@@ -63,7 +63,7 @@
 import           Data.Text (pack)
 import           Stack.Prelude
 import           System.FilePath (takeExtension)
-import           System.IO (stderr, hPutStrLn)
+import           System.IO (hPutStrLn)
 
 -- | Parser to extract the stack command line embedded inside a comment
 -- after validating the placement and formatting rules for a valid
diff --git a/src/Network/HTTP/StackClient.hs b/src/Network/HTTP/StackClient.hs
--- a/src/Network/HTTP/StackClient.hs
+++ b/src/Network/HTTP/StackClient.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-
+{-# LANGUAGE LambdaCase        #-}
 -- |
 -- Wrapper functions of 'Network.HTTP.Simple' and 'Network.HTTP.Client' to
 -- add the 'User-Agent' HTTP request header to each request.
@@ -43,17 +43,28 @@
   , download
   , redownload
   , verifiedDownload
+  , verifiedDownloadWithProgress
   , CheckHexDigest (..)
-  , DownloadRequest (..)
+  , DownloadRequest
   , drRetryPolicyDefault
-  , DownloadException (..)
+  , VerifiedDownloadException (..)
   , HashCheck (..)
+  , mkDownloadRequest
+  , setHashChecks
+  , setLengthCheck
+  , setRetryPolicy
+  , setForceDownload
   ) where
 
+import           Control.Monad.State (get, put, modify)
 import           Data.Aeson (FromJSON)
 import qualified Data.ByteString as Strict
-import           Data.Conduit (ConduitM)
-import           Data.Void (Void)
+import           Data.Conduit (ConduitM, ConduitT, awaitForever, (.|), yield, await)
+import           Data.Conduit.Lift (evalStateC)
+import qualified Data.Conduit.List as CL
+import           Data.Monoid (Sum (..))
+import qualified Data.Text as T
+import           Data.Time.Clock (NominalDiffTime, diffUTCTime, getCurrentTime)
 import           Network.HTTP.Client (Request, RequestBody(..), Response, parseRequest, getUri, path, checkResponse, parseUrlThrow)
 import           Network.HTTP.Simple (setRequestMethod, setRequestBody, setRequestHeader, addRequestHeader, HttpException(..), getResponseBody, getResponseStatusCode, getResponseHeaders)
 import           Network.HTTP.Types (hAccept, hContentLength, hContentMD5, methodPut)
@@ -64,8 +75,10 @@
 import qualified Network.HTTP.Simple
 import           Network.HTTP.Client.MultipartFormData (formDataBody, partFileRequestBody, partBS, partLBS)
 import           Path
+import           Prelude (until, (!!))
 import           RIO
 import           RIO.PrettyPrint
+import           Text.Printf (printf)
 
 
 setUserAgent :: Request -> Request
@@ -144,4 +157,97 @@
 verifiedDownload dr destpath progressSink =
     Download.verifiedDownload dr' destpath progressSink
   where
-    dr' = dr {drRequest = setUserAgent (drRequest dr)}
+    dr' = modifyRequest setUserAgent dr
+
+verifiedDownloadWithProgress
+  :: HasTerm env
+  => DownloadRequest
+  -> Path Abs File
+  -> Text
+  -> Maybe Int
+  -> RIO env Bool
+verifiedDownloadWithProgress req destpath lbl msize =
+  verifiedDownload req destpath (chattyDownloadProgress lbl msize)
+
+chattyDownloadProgress
+  :: ( HasLogFunc env
+     , MonadIO m
+     , MonadReader env m
+     )
+  => Text
+  -> Maybe Int
+  -> f
+  -> ConduitT ByteString c m ()
+chattyDownloadProgress label mtotalSize _ = do
+    _ <- logSticky $ RIO.display label <> ": download has begun"
+    CL.map (Sum . Strict.length)
+      .| chunksOverTime 1
+      .| go
+  where
+    go = evalStateC 0 $ awaitForever $ \(Sum size) -> do
+        modify (+ size)
+        totalSoFar <- get
+        logSticky $ fromString $
+            case mtotalSize of
+                Nothing -> chattyProgressNoTotal totalSoFar
+                Just 0 -> chattyProgressNoTotal totalSoFar
+                Just totalSize -> chattyProgressWithTotal totalSoFar totalSize
+
+    -- Example: ghc: 42.13 KiB downloaded...
+    chattyProgressNoTotal totalSoFar =
+        printf ("%s: " <> bytesfmt "%7.2f" totalSoFar <> " downloaded...")
+                (T.unpack label)
+
+    -- Example: ghc: 50.00 MiB / 100.00 MiB (50.00%) downloaded...
+    chattyProgressWithTotal totalSoFar total =
+      printf ("%s: " <>
+              bytesfmt "%7.2f" totalSoFar <> " / " <>
+              bytesfmt "%.2f" total <>
+              " (%6.2f%%) downloaded...")
+              (T.unpack label)
+              percentage
+      where percentage :: Double
+            percentage = fromIntegral totalSoFar / fromIntegral total * 100
+
+-- | Given a printf format string for the decimal part and a number of
+-- bytes, formats the bytes using an appropriate unit and returns the
+-- formatted string.
+--
+-- >>> bytesfmt "%.2" 512368
+-- "500.359375 KiB"
+bytesfmt :: Integral a => String -> a -> String
+bytesfmt formatter bs = printf (formatter <> " %s")
+                               (fromIntegral (signum bs) * dec :: Double)
+                               (bytesSuffixes !! i)
+  where
+    (dec,i) = getSuffix (abs bs)
+    getSuffix n = until p (\(x,y) -> (x / 1024, y+1)) (fromIntegral n,0)
+      where p (n',numDivs) = n' < 1024 || numDivs == (length bytesSuffixes - 1)
+    bytesSuffixes :: [String]
+    bytesSuffixes = ["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]
+
+-- Await eagerly (collect with monoidal append),
+-- but space out yields by at least the given amount of time.
+-- The final yield may come sooner, and may be a superfluous mempty.
+-- Note that Integer and Float literals can be turned into NominalDiffTime
+-- (these literals are interpreted as "seconds")
+chunksOverTime :: (Monoid a, Semigroup a, MonadIO m) => NominalDiffTime -> ConduitM a a m ()
+chunksOverTime diff = do
+    currentTime <- liftIO getCurrentTime
+    evalStateC (currentTime, mempty) go
+  where
+    -- State is a tuple of:
+    -- * the last time a yield happened (or the beginning of the sink)
+    -- * the accumulated awaits since the last yield
+    go = await >>= \case
+      Nothing -> do
+        (_, acc) <- get
+        yield acc
+      Just a -> do
+        (lastTime, acc) <- get
+        let acc' = acc <> a
+        currentTime <- liftIO getCurrentTime
+        if diff < diffUTCTime currentTime lastTime
+          then put (currentTime, mempty) >> yield acc'
+          else put (lastTime,    acc')
+        go
diff --git a/src/Path/Extended.hs b/src/Path/Extended.hs
new file mode 100644
--- /dev/null
+++ b/src/Path/Extended.hs
@@ -0,0 +1,40 @@
+{-# LANGUAGE CPP #-}
+
+module Path.Extended 
+ ( fileExtension
+ , addExtension
+ , replaceExtension
+ ) where
+
+import           Control.Monad.Catch
+import qualified Path
+import           Path (Path, File)
+
+fileExtension :: MonadThrow m => Path b File -> m String
+fileExtension = 
+#if MIN_VERSION_path(0,7,0)
+    Path.fileExtension
+#else
+    pure . Path.fileExtension
+#endif
+
+addExtension :: MonadThrow m
+  => String
+  -> Path b File
+  -> m (Path b File)
+addExtension =
+#if MIN_VERSION_path(0,7,0)
+    Path.addExtension
+#else
+    Path.addFileExtension
+#endif
+
+replaceExtension :: MonadThrow m
+  => String
+  -> Path b File
+  -> m (Path b File)
+#if MIN_VERSION_path(0,7,0)
+replaceExtension ext = Path.replaceExtension ('.' : ext)
+#else
+replaceExtension = flip (Path.-<.>)
+#endif
diff --git a/src/Path/Extra.hs b/src/Path/Extra.hs
--- a/src/Path/Extra.hs
+++ b/src/Path/Extra.hs
@@ -17,7 +17,6 @@
   ,tryGetModificationTime
   ) where
 
-import           Data.Bool (bool)
 import           Data.Time (UTCTime)
 import           Path
 import           Path.IO
diff --git a/src/Stack/Build.hs b/src/Stack/Build.hs
--- a/src/Stack/Build.hs
+++ b/src/Stack/Build.hs
@@ -21,7 +21,6 @@
 import qualified Data.HashMap.Strict as HM
 import           Data.List ((\\), isPrefixOf)
 import           Data.List.Extra (groupSort)
-import           Data.List.NonEmpty (NonEmpty(..))
 import qualified Data.List.NonEmpty as NE
 import qualified Data.Map as Map
 import qualified Data.Set as Set
@@ -31,6 +30,8 @@
 import           Data.Text.Read (decimal)
 import qualified Data.Vector as V
 import qualified Data.Yaml as Yaml
+import qualified Distribution.PackageDescription as C
+import           Distribution.Types.Dependency (depLibraries)
 import           Distribution.Version (mkVersion)
 import           Path (parent)
 import           Stack.Build.ConstructPlan
@@ -65,6 +66,8 @@
     depsLocals <- localDependencies
     let allLocals = locals <> depsLocals
 
+    checkSubLibraryDependencies (Map.elems $ smProject sourceMap)
+
     -- Set local files, necessary for file watching
     stackYaml <- view stackYamlL
     for_ msetLocalFiles $ \setLocalFiles -> do
@@ -334,3 +337,28 @@
         | lp <- lps
         , c <- Set.toList (lpUnbuildable lp)
         ]
+
+-- | Find if sublibrary dependency exist in each project
+checkSubLibraryDependencies :: HasLogFunc env => [ProjectPackage] -> RIO env ()
+checkSubLibraryDependencies proj = do
+  forM_ proj $ \p -> do
+    C.GenericPackageDescription _ _ lib subLibs foreignLibs exes tests benches <- liftIO $ cpGPD . ppCommon $ p
+
+    let dependencies = concatMap getDeps subLibs <>
+                       concatMap getDeps foreignLibs <>
+                       concatMap getDeps exes <>
+                       concatMap getDeps tests <>
+                       concatMap getDeps benches <>
+                       maybe [] C.condTreeConstraints lib
+        libraries = concatMap (toList . depLibraries) dependencies
+
+    when (subLibDepExist libraries)
+      (logWarn "SubLibrary dependency is not supported, this will almost certainly fail")
+  where
+    getDeps (_, C.CondNode _ dep _) = dep
+    subLibDepExist lib = 
+      any (\x ->
+        case x of
+          C.LSubLibName _ -> True
+          C.LMainLibName  -> False
+      ) lib
diff --git a/src/Stack/Build/Cache.hs b/src/Stack/Build/Cache.hs
--- a/src/Stack/Build/Cache.hs
+++ b/src/Stack/Build/Cache.hs
@@ -11,6 +11,7 @@
     ( tryGetBuildCache
     , tryGetConfigCache
     , tryGetCabalMod
+    , tryGetSetupConfigMod
     , getInstalledExes
     , tryGetFlagCache
     , deleteCaches
@@ -138,6 +139,17 @@
                => Path Abs Dir -> RIO env (Maybe CTime)
 tryGetCabalMod dir = do
   fp <- toFilePath <$> configCabalMod dir
+  tryGetFileMod fp
+
+-- | Try to read the mod time of setup-config file from the last build
+tryGetSetupConfigMod :: HasEnvConfig env
+               => Path Abs Dir -> RIO env (Maybe CTime)
+tryGetSetupConfigMod dir = do
+  fp <- toFilePath <$> configSetupConfigMod dir
+  tryGetFileMod fp
+
+tryGetFileMod :: MonadIO m => FilePath -> m (Maybe CTime)
+tryGetFileMod fp =
   liftIO $ either (const Nothing) (Just . modificationTime) <$>
       tryIO (getFileStatus fp)
 
diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs
--- a/src/Stack/Build/ConstructPlan.hs
+++ b/src/Stack/Build/ConstructPlan.hs
@@ -22,12 +22,9 @@
 import           Data.Monoid.Map (MonoidMap(..))
 import qualified Data.Set as Set
 import qualified Data.Text as T
-import           Data.Text.Encoding (encodeUtf8, decodeUtf8With)
-import           Data.Text.Encoding.Error (lenientDecode)
 import qualified Distribution.Text as Cabal
 import qualified Distribution.Version as Cabal
 import           Distribution.Types.BuildType (BuildType (Configure))
-import           Distribution.Types.PackageId (pkgVersion)
 import           Distribution.Types.PackageName (mkPackageName)
 import           Distribution.Version (mkVersion)
 import           Generics.Deriving.Monoid (memptydefault, mappenddefault)
@@ -206,10 +203,11 @@
                 tasks = M.fromList $ mapMaybe toTask adrs
                 takeSubset =
                     case boptsCLIBuildSubset $ bcoBuildOptsCLI baseConfigOpts0 of
-                        BSAll -> id
-                        BSOnlySnapshot -> stripLocals
-                        BSOnlyDependencies -> stripNonDeps (M.keysSet $ smDeps sourceMap)
-            return $ takeSubset Plan
+                        BSAll -> pure
+                        BSOnlySnapshot -> pure . stripLocals
+                        BSOnlyDependencies -> pure . stripNonDeps (M.keysSet $ smDeps sourceMap)
+                        BSOnlyLocals -> errorOnSnapshot
+            takeSubset Plan
                 { planTasks = tasks
                 , planFinals = M.fromList finals
                 , planUnregisterLocal = mkUnregisterLocal tasks dirtyReason localDumpPkgs initialBuildSteps
@@ -270,6 +268,33 @@
             return $ PSFilePath lp
       return $ pPackages <> deps
 
+-- | Throw an exception if there are any snapshot packages in the plan.
+errorOnSnapshot :: Plan -> RIO env Plan
+errorOnSnapshot plan@(Plan tasks _finals _unregister installExes) = do
+  let snapTasks = Map.keys $ Map.filter (\t -> taskLocation t == Snap) tasks
+  let snapExes = Map.keys $ Map.filter (== Snap) installExes
+  unless (null snapTasks && null snapExes) $ throwIO $
+    NotOnlyLocal snapTasks snapExes
+  pure plan
+
+data NotOnlyLocal = NotOnlyLocal [PackageName] [Text]
+
+instance Show NotOnlyLocal where
+  show (NotOnlyLocal packages exes) = concat
+    [ "Specified only-locals, but I need to build snapshot contents:\n"
+    , if null packages then "" else concat
+        [ "Packages: "
+        , intercalate ", " (map packageNameString packages)
+        , "\n"
+        ]
+    , if null exes then "" else concat
+        [ "Executables: "
+        , intercalate ", " (map T.unpack exes)
+        , "\n"
+        ]
+    ]
+instance Exception NotOnlyLocal
+
 -- | State to be maintained during the calculation of local packages
 -- to unregister.
 data UnregisterState = UnregisterState
@@ -842,10 +867,6 @@
         go ("--ghc-options":x:xs) = go' Ghc x xs
         go ((T.stripPrefix "--ghc-option=" -> Just x):xs) = go' Ghc x xs
         go ((T.stripPrefix "--ghc-options=" -> Just x):xs) = go' Ghc x xs
-        go ("--ghcjs-option":x:xs) = go' Ghcjs x xs
-        go ("--ghcjs-options":x:xs) = go' Ghcjs x xs
-        go ((T.stripPrefix "--ghcjs-option=" -> Just x):xs) = go' Ghcjs x xs
-        go ((T.stripPrefix "--ghcjs-options=" -> Just x):xs) = go' Ghcjs x xs
         go (x:xs) = x : go xs
 
         go' wc x xs = checkKeepers wc x $ go xs
@@ -1109,7 +1130,7 @@
             let prunedDeps = map (style Current . fromString . packageNameString) pruned
             in Just $ flow "Can't use GHC boot package" <+>
                       (style Current . fromString . packageNameString $ name) <+>
-                      flow "when it has an overriden dependency, " <+>
+                      flow "when it has an overridden dependency (issue #4510);" <+>
                       flow "you need to add the following as explicit dependencies to the project:" <+>
                       line <+> encloseSep "" "" ", " prunedDeps
         | otherwise = Just $ flow "Unknown package:" <+> (style Current . fromString . packageNameString $ name)
@@ -1121,13 +1142,22 @@
     pprintFlag (name, False) = "-" <> fromString (flagNameString name)
 
     pprintDep (name, (range, mlatestApplicable, badDep)) = case badDep of
-        NotInBuildPlan -> Just $
-            style Error (fromString $ packageNameString name) <+>
-            align ((if range == Cabal.anyVersion
-                      then flow "needed"
-                      else flow "must match" <+> goodRange) <> "," <> softline <>
-                   flow "but the stack configuration has no specified version" <+>
-                   latestApplicable Nothing)
+        NotInBuildPlan
+          | name `elem` fold prunedGlobalDeps -> Just $
+              style Error (fromString $ packageNameString name) <+>
+              align ((if range == Cabal.anyVersion
+                        then flow "needed"
+                        else flow "must match" <+> goodRange) <> "," <> softline <>
+                     flow "but this GHC boot package has been pruned (issue #4510);" <+>
+                     flow "you need to add the package explicitly to extra-deps" <+>
+                     latestApplicable Nothing)
+          | otherwise -> Just $
+              style Error (fromString $ packageNameString name) <+>
+              align ((if range == Cabal.anyVersion
+                        then flow "needed"
+                        else flow "must match" <+> goodRange) <> "," <> softline <>
+                     flow "but the stack configuration has no specified version" <+>
+                     latestApplicable Nothing)
         -- TODO: For local packages, suggest editing constraints
         DependencyMismatch version -> Just $
             (style Error . fromString . packageIdentifierString) (PackageIdentifier name version) <+>
diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs
--- a/src/Stack/Build/Execute.hs
+++ b/src/Stack/Build/Execute.hs
@@ -40,15 +40,17 @@
 import           Data.Conduit.Process.Typed (createSource)
 import qualified Data.Conduit.Text as CT
 import           Data.List hiding (any)
-import           Data.List.NonEmpty (NonEmpty(..), nonEmpty)
+import           Data.List.NonEmpty (nonEmpty)
 import qualified Data.List.NonEmpty as NonEmpty (toList)
 import           Data.List.Split (chunksOf)
 import qualified Data.Map.Strict as M
 import qualified Data.Map.Strict as Map
 import qualified Data.Set as Set
 import qualified Data.Text as T
-import           Data.Text.Encoding (decodeUtf8, encodeUtf8)
+import           Data.Text.Encoding (decodeUtf8)
 import           Data.Tuple
+import           Data.Time (ZonedTime, getZonedTime, formatTime, defaultTimeLocale)
+import qualified Data.ByteString.Char8 as S8
 import qualified Distribution.PackageDescription as C
 import qualified Distribution.Simple.Build.Macros as C
 import           Distribution.System            (OS (Windows),
@@ -87,7 +89,7 @@
 import           System.Environment (getExecutablePath, lookupEnv)
 import           System.FileLock (withTryFileLock, SharedExclusive (Exclusive), withFileLock)
 import qualified System.FilePath as FP
-import           System.IO (stderr, stdout)
+import           System.IO.Error (isDoesNotExistError)
 import           System.PosixCompat.Files (createLink, modificationTime, getFileStatus)
 import           System.PosixCompat.Time (epochTime)
 import           RIO.PrettyPrint
@@ -267,16 +269,12 @@
         outputNameS =
             case wc of
                 Ghc -> exeNameS
-                Ghcjs -> baseNameS ++ ".jsexe"
-        jsExeNameS =
-            baseNameS ++ ".jsexe"
         setupDir =
             view stackRootL config </>
             relDirSetupExeCache </>
             platformDir
 
     exePath <- (setupDir </>) <$> parseRelFile exeNameS
-    jsExePath <- (setupDir </>) <$> parseRelDir jsExeNameS
 
     exists <- liftIO $ D.doesFileExist $ toFilePath exePath
 
@@ -285,7 +283,6 @@
         else do
             tmpExePath <- fmap (setupDir </>) $ parseRelFile $ "tmp-" ++ exeNameS
             tmpOutputPath <- fmap (setupDir </>) $ parseRelFile $ "tmp-" ++ outputNameS
-            tmpJsExePath <- fmap (setupDir </>) $ parseRelDir $ "tmp-" ++ jsExeNameS
             ensureDir setupDir
             let args = buildSetupArgs ++
                     [ "-package"
@@ -294,15 +291,13 @@
                     , toFilePath setupShimHs
                     , "-o"
                     , toFilePath tmpOutputPath
-                    ] ++
-                    ["-build-runner" | wc == Ghcjs]
+                    ]
             compilerPath <- getCompilerPath
             withWorkingDir (toFilePath tmpdir) (proc (toFilePath compilerPath) args $ \pc0 -> do
               let pc = setStdout (useHandleOpen stderr) pc0
               runProcess_ pc)
                 `catch` \ece ->
                     throwM $ SetupHsBuildFailure (eceExitCode ece) Nothing compilerPath args Nothing []
-            when (wc == Ghcjs) $ renameDir tmpJsExePath jsExePath
             renameFile tmpExePath exePath
             return $ Just exePath
 
@@ -687,9 +682,9 @@
             unregisterGhcPkgIds pkg localDB $ select ident gid :| []
 
     case cv of
-        -- GHC versions >= 8.0.1 support batch unregistering of packages. See
-        -- https://github.com/commercialhaskell/stack/pull/4554
-        ACGhc v | v >= mkVersion [8, 0, 1] -> do
+        -- GHC versions >= 8.2.1 support batch unregistering of packages. See
+        -- https://gitlab.haskell.org/ghc/ghc/issues/12637
+        ACGhc v | v >= mkVersion [8, 2, 1] -> do
                 platform <- view platformL
                 -- According to https://support.microsoft.com/en-us/help/830473/command-prompt-cmd-exe-command-line-string-limitation
                 -- the maximum command line length on Windows since XP is 8191 characters.
@@ -851,6 +846,9 @@
              -> RIO env Bool
 ensureConfig newConfigCache pkgDir ExecuteEnv {..} announce cabal cabalfp task = do
     newCabalMod <- liftIO $ modificationTime <$> getFileStatus (toFilePath cabalfp)
+    setupConfigfp <- setupConfigFromDir pkgDir
+    newSetupConfigMod <- liftIO $ either (const Nothing) (Just . modificationTime) <$>
+      tryJust (guard . isDoesNotExistError) (getFileStatus (toFilePath setupConfigfp))
     -- See https://github.com/commercialhaskell/stack/issues/3554
     taskAnyMissingHack <- view $ actualCompilerVersionL.to getGhcVersion.to (< mkVersion [8, 4])
     needConfig <-
@@ -869,8 +867,13 @@
 
                 mOldCabalMod <- tryGetCabalMod pkgDir
 
+                -- Cabal's setup-config is created per OS/Cabal version, multiple
+                -- projects using the same package could get a conflict because of this
+                mOldSetupConfigMod <- tryGetSetupConfigMod pkgDir
+
                 return $ fmap ignoreComponents mOldConfigCache /= Just (ignoreComponents newConfigCache)
                       || mOldCabalMod /= Just newCabalMod
+                      || mOldSetupConfigMod /= newSetupConfigMod
     let ConfigureOpts dirs nodirs = configCacheOpts newConfigCache
 
     when (taskBuildTypeConfig task) ensureConfigureScript
@@ -886,7 +889,6 @@
                   [ "--with-ghc=" ++ toFilePath (cpCompiler cp)
                   , "--with-ghc-pkg=" ++ toFilePath pkgPath
                   ]
-                Ghcjs -> []
         exes <- forM programNames $ \name -> do
             mpath <- findExecutable name
             return $ case mpath of
@@ -923,7 +925,7 @@
             -- On Windows 10, an upstream issue with the `sh autoreconf -i`
             -- command means that command clears, but does not then restore, the
             -- ENABLE_VIRTUAL_TERMINAL_PROCESSING flag for native terminals. The
-            -- folowing hack re-enables the lost ANSI-capability.
+            -- following hack re-enables the lost ANSI-capability.
             fixupOnWindows = when osIsWindows (void $ liftIO defaultColorWhen)
         withWorkingDir (toFilePath pkgDir) $ autoreconf `catchAny` \ex -> do
           fixupOnWindows
@@ -1292,15 +1294,14 @@
                   where
                     runAndOutput :: ActualCompiler -> RIO env ()
                     runAndOutput compilerVer = withWorkingDir (toFilePath pkgDir) $ withProcessContext menv $ case outputType of
-                        OTLogFile _ h ->
-                            proc (toFilePath exeName) fullArgs
-                          $ runProcess_
-                            -- Don't use closed, since that can break
-                            -- ./configure scripts. See:
-                            -- https://github.com/commercialhaskell/stack/pull/4722
-                          . setStdin (byteStringInput "")
-                          . setStdout (useHandleOpen h)
-                          . setStderr (useHandleOpen h)
+                        OTLogFile _ h -> do
+                          let prefixWithTimestamps =
+                                if configPrefixTimestamps config
+                                   then PrefixWithTimestamps
+                                   else WithoutTimestamps
+                          void $ sinkProcessStderrStdout (toFilePath exeName) fullArgs
+                              (sinkWithTimestamps prefixWithTimestamps h)
+                              (sinkWithTimestamps prefixWithTimestamps h)
                         OTConsole mprefix ->
                             let prefix = fold mprefix in
                             void $ sinkProcessStderrStdout (toFilePath exeName) fullArgs
@@ -1334,7 +1335,6 @@
                         then return outputFile
                         else do
                             ensureDir setupDir
-                            compiler <- view $ actualCompilerVersionL.whichCompilerL
                             compilerPath <- view $ compilerPathsL.to cpCompiler
                             packageArgs <- getPackageArgs setupDir
                             runExe compilerPath $
@@ -1350,9 +1350,6 @@
                                 , "-o", toFilePath outputFile
                                 , "-threaded"
                                 ] ++
-                                (case compiler of
-                                    Ghc -> []
-                                    Ghcjs -> ["-build-runner"]) ++
 
                                 -- Apply GHC options
                                 -- https://github.com/commercialhaskell/stack/issues/4526
@@ -1557,7 +1554,6 @@
                        "' once. After a successful build of all of them, only specified executables will be rebuilt."))
 
             _neededConfig <- ensureConfig cache pkgDir ee (announce ("configure" <> RIO.display (annSuffix executableBuildStatuses))) cabal cabalfp task
-
             let installedMapHasThisPkg :: Bool
                 installedMapHasThisPkg =
                     case Map.lookup (packageName package) installedMap of
@@ -1787,7 +1783,7 @@
             [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"
+            _ -> error $ "singleBuild: invariant violated: multiple results when describing installed package " ++ show (name, dps)
 
 -- | Get the build status of all the package executables. Do so by
 -- testing whether their expected output file exists, e.g.
@@ -1799,22 +1795,20 @@
     :: HasEnvConfig env
     => Package -> Path Abs Dir -> RIO env (Map Text ExecutableBuildStatus)
 getExecutableBuildStatuses package pkgDir = do
-    compiler <- view $ actualCompilerVersionL.whichCompilerL
     distDir <- distDirFromDir pkgDir
     platform <- view platformL
     fmap
         M.fromList
-        (mapM (checkExeStatus compiler platform distDir) (Set.toList (packageExes package)))
+        (mapM (checkExeStatus platform distDir) (Set.toList (packageExes package)))
 
 -- | Check whether the given executable is defined in the given dist directory.
 checkExeStatus
     :: HasLogFunc env
-    => WhichCompiler
-    -> Platform
+    => Platform
     -> Path b Dir
     -> Text
     -> RIO env (Text, ExecutableBuildStatus)
-checkExeStatus compiler platform distDir name = do
+checkExeStatus platform distDir name = do
     exename <- parseRelDir (T.unpack name)
     exists <- checkPath (distDir </> relDirBuild </> exename)
     pure
@@ -1824,18 +1818,13 @@
               else ExecutableNotBuilt)
   where
     checkPath base =
-        case compiler of
-            Ghcjs -> do
-                dir <- parseRelDir (file ++ ".jsexe")
-                doesDirExist (base </> dir)
-            _ ->
-                case platform of
-                    Platform _ Windows -> do
-                        fileandext <- parseRelFile (file ++ ".exe")
-                        doesFileExist (base </> fileandext)
-                    _ -> do
-                        fileandext <- parseRelFile file
-                        doesFileExist (base </> fileandext)
+        case platform of
+            Platform _ Windows -> do
+                fileandext <- parseRelFile (file ++ ".exe")
+                doesFileExist (base </> fileandext)
+            _ -> do
+                fileandext <- parseRelFile file
+                doesFileExist (base </> fileandext)
       where
         file = T.unpack name
 
@@ -2192,6 +2181,28 @@
            >> char ':'
            >> return ()
         where num = some digit
+
+-- | Whether to prefix log lines with timestamps.
+data PrefixWithTimestamps = PrefixWithTimestamps | WithoutTimestamps
+
+-- | Write stream of lines to handle, but adding timestamps.
+sinkWithTimestamps :: MonadIO m => PrefixWithTimestamps -> Handle -> ConduitT ByteString Void m ()
+sinkWithTimestamps prefixWithTimestamps h =
+    case prefixWithTimestamps of
+        PrefixWithTimestamps ->
+            CB.lines .| CL.mapM addTimestamp .| CL.map (<> "\n") .| sinkHandle h
+        WithoutTimestamps -> sinkHandle h
+  where
+    addTimestamp theLine = do
+        now <- liftIO getZonedTime
+        pure (formatZonedTimeForLog now <> " " <> theLine)
+
+-- | Format a time in ISO8601 format. We choose ZonedTime over UTCTime
+-- because a user expects to see logs in their local time, and would
+-- be confused to see UTC time. Stack's debug logs also use the local
+-- time zone.
+formatZonedTimeForLog :: ZonedTime -> ByteString
+formatZonedTimeForLog = S8.pack . formatTime defaultTimeLocale "%Y-%m-%dT%H:%M:%S%6Q"
 
 -- | Find the Setup.hs or Setup.lhs in the given directory. If none exists,
 -- throw an exception.
diff --git a/src/Stack/Build/Haddock.hs b/src/Stack/Build/Haddock.hs
--- a/src/Stack/Build/Haddock.hs
+++ b/src/Stack/Build/Haddock.hs
@@ -229,8 +229,10 @@
                         docRelFP FP.</>
                         packageIdentifierString dpPackageIdent FP.</>
                         (packageNameString name FP.<.> "haddock")
+                    docPathRelFP =
+                        fmap ((docRelFP FP.</>) . FP.takeFileName) dpHaddockHtml
                     interfaces = intercalate "," $
-                      maybeToList dpHaddockHtml ++ [srcInterfaceFP]
+                        maybeToList docPathRelFP ++ [srcInterfaceFP]
 
                 destInterfaceAbsFile <- parseCollapsedAbsFile (toFilePath destDir FP.</> destInterfaceRelFP)
                 esrcInterfaceModTime <- tryGetModificationTime srcInterfaceAbsFile
diff --git a/src/Stack/Build/Installed.hs b/src/Stack/Build/Installed.hs
--- a/src/Stack/Build/Installed.hs
+++ b/src/Stack/Build/Installed.hs
@@ -24,7 +24,6 @@
 import           Stack.Prelude
 import           Stack.SourceMap (getPLIVersion, loadVersion)
 import           Stack.Types.Build
-import           Stack.Types.Compiler
 import           Stack.Types.Config
 import           Stack.Types.GhcPkgId
 import           Stack.Types.Package
@@ -116,12 +115,10 @@
              -> [LoadHelper] -- ^ from parent databases
              -> RIO env ([LoadHelper], [DumpPackage])
 loadDatabase installMap mdb lhs0 = do
-    wc <- view $ actualCompilerVersionL.to whichCompiler
     pkgexe <- getGhcPkgExe
     (lhs1', dps) <- ghcPkgDump pkgexe (fmap snd (maybeToList mdb))
                 $ conduitDumpPackage .| sink
-    let ghcjsHack = wc == Ghcjs && isNothing mdb
-    lhs1 <- mapMaybeM (processLoadResult mdb ghcjsHack) lhs1'
+    lhs1 <- mapMaybeM (processLoadResult mdb) lhs1'
     let lhs = pruneDeps
             id
             lhId
@@ -139,23 +136,10 @@
 
 processLoadResult :: HasLogFunc env
                   => Maybe (InstalledPackageLocation, Path Abs Dir)
-                  -> Bool
                   -> (Allowed, LoadHelper)
                   -> RIO env (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) `Set.member` ghcjsBootPackages = do
-        logWarn $
-            "Ignoring that the GHCJS boot package \"" <>
-            fromString (packageNameString (fst (lhPair lh))) <>
-            "\" has a different version, " <>
-            fromString (versionString actual) <>
-            ", than the resolver's wanted version, " <>
-            fromString (versionString wanted)
-        return (Just lh)
-processLoadResult mdb _ (reason, lh) = do
+processLoadResult _ (Allowed, lh) = return (Just lh)
+processLoadResult mdb (reason, lh) = do
     logDebug $
         "Ignoring package " <>
         fromString (packageNameString (fst (lhPair lh))) <>
diff --git a/src/Stack/BuildPlan.hs b/src/Stack/BuildPlan.hs
--- a/src/Stack/BuildPlan.hs
+++ b/src/Stack/BuildPlan.hs
@@ -25,7 +25,6 @@
 import qualified Data.Foldable as F
 import qualified Data.Set as Set
 import           Data.List (intercalate)
-import           Data.List.NonEmpty (NonEmpty(..))
 import qualified Data.List.NonEmpty as NonEmpty
 import qualified Data.Map as Map
 import qualified Data.Text as T
@@ -372,7 +371,6 @@
     where
         compilerErrors compiler errs
             | whichCompiler compiler == Ghc = ghcErrors errs
-            -- FIXME not sure how to handle ghcjs boot packages
             | otherwise = Map.empty
 
         isGhcWiredIn p _ = p `Set.member` wiredInPackages
diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs
--- a/src/Stack/Config.hs
+++ b/src/Stack/Config.hs
@@ -44,7 +44,6 @@
 import qualified Data.Monoid
 import           Data.Monoid.Map (MonoidMap(..))
 import qualified Data.Text as T
-import           Data.Text.Encoding (encodeUtf8)
 import qualified Data.Yaml as Yaml
 import           Distribution.System (OS (..), Platform (..), buildPlatform, Arch(OtherArch))
 import qualified Distribution.Text
@@ -146,7 +145,6 @@
     -> RIO env RawSnapshotLocation
 makeConcreteResolver (ARResolver r) = pure r
 makeConcreteResolver ar = do
-    snapshots <- getSnapshots
     r <-
         case ar of
             ARResolver r -> assert False $ makeConcreteResolver (ARResolver r)
@@ -157,16 +155,18 @@
                 iopc <- loadConfigYaml (parseProjectAndConfigMonoid (parent fp)) fp
                 ProjectAndConfigMonoid project _ <- liftIO iopc
                 return $ projectResolver project
-            ARLatestNightly -> return $ nightlySnapshotLocation $ snapshotsNightly snapshots
-            ARLatestLTSMajor x ->
+            ARLatestNightly -> nightlySnapshotLocation . snapshotsNightly <$> getSnapshots
+            ARLatestLTSMajor x -> do
+                snapshots <- getSnapshots
                 case IntMap.lookup x $ snapshotsLts snapshots of
                     Nothing -> throwString $ "No LTS release found with major version " ++ show x
                     Just y -> return $ ltsSnapshotLocation x y
-            ARLatestLTS
-                | IntMap.null $ snapshotsLts snapshots -> throwString "No LTS releases found"
-                | otherwise ->
-                    let (x, y) = IntMap.findMax $ snapshotsLts snapshots
-                     in return $ ltsSnapshotLocation x y
+            ARLatestLTS -> do
+                snapshots <- getSnapshots
+                if IntMap.null $ snapshotsLts snapshots
+                   then throwString "No LTS releases found"
+                   else let (x, y) = IntMap.findMax $ snapshotsLts snapshots
+                        in return $ ltsSnapshotLocation x y
     logInfo $ "Selected resolver: " <> display r
     return r
 
@@ -211,6 +211,7 @@
            configMonoidLatestSnapshot
          clConnectionCount = fromFirst 8 configMonoidConnectionCount
          configHideTHLoading = fromFirstTrue configMonoidHideTHLoading
+         configPrefixTimestamps = fromFirst False configMonoidPrefixTimestamps
 
          configGHCVariant = getFirst configMonoidGHCVariant
          configCompilerRepository = fromFirst
@@ -281,12 +282,12 @@
        shortLocalProgramsFilePath <-
          liftIO $ getShortPathName localProgramsFilePath
        when (' ' `elem` shortLocalProgramsFilePath) $ do
-         logWarn $ "Stack's 'programs' path contains a space character and " <>
+         logError $ "Stack's 'programs' path contains a space character and " <>
            "has no alternative short ('8 dot 3') name. This will cause " <>
            "problems with packages that use the GNU project's 'configure' " <>
-           "shell script. Use the 'local-programs-path' configuation option " <>
-           "to specify an alternative path. The current 'shortest' path is: " <>
-           display (T.pack shortLocalProgramsFilePath)
+           "shell script. Use the 'local-programs-path' configuration option " <>
+           "to specify an alternative path. The current path is: " <>
+           display (T.pack localProgramsFilePath)
      platformOnlyDir <- runReaderT platformOnlyRelDir (configPlatform, configPlatformVariant)
      let configLocalPrograms = configLocalProgramsBase </> platformOnlyDir
 
@@ -319,6 +320,7 @@
          configGhcOptionsByName = coerce configMonoidGhcOptionsByName
          configGhcOptionsByCat = coerce configMonoidGhcOptionsByCat
          configSetupInfoLocations = configMonoidSetupInfoLocations
+         configSetupInfoInline = configMonoidSetupInfoInline
          configPvpBounds = fromFirst (PvpBounds PvpBoundsNone False) configMonoidPvpBounds
          configModifyCodePage = fromFirstTrue configMonoidModifyCodePage
          configExplicitSetupDeps = configMonoidExplicitSetupDeps
@@ -374,6 +376,8 @@
        hsc
        (maybe HpackBundled HpackCommand $ getFirst configMonoidOverrideHpack)
        clConnectionCount
+       (fromFirst defaultCasaRepoPrefix configMonoidCasaRepoPrefix)
+       defaultCasaMaxPerRequest
        (\configPantryConfig -> initUserStorage
          (configStackRoot </> relFileStorage)
          (\configUserStorage -> inner Config {..}))
@@ -587,8 +591,17 @@
     (deps0, mcompleted) <- fmap unzip . forM (projectDependencies project) $ \rpl -> do
       (pl, mCompleted) <- case rpl of
          RPLImmutable rpli -> do
-           compl <- maybe (completePackageLocation rpli) pure (Map.lookup rpli locCache)
-           pure (PLImmutable compl, Just (CompletedPLI rpli compl))
+           (compl, mcompl) <-
+             case Map.lookup rpli locCache of
+               Just compl -> pure (compl, Just compl)
+               Nothing -> do
+                 cpl <- completePackageLocation rpli
+                 if cplHasCabalFile cpl
+                   then pure (cplComplete cpl, Just $ cplComplete cpl)
+                   else do
+                     warnMissingCabalFile rpli
+                     pure (cplComplete cpl, Nothing)
+           pure (PLImmutable compl, CompletedPLI rpli <$> mcompl)
          RPLMutable p ->
            pure (PLMutable p, Nothing)
       dp <- additionalDepPackage (shouldHaddockDeps bopts) pl
diff --git a/src/Stack/ConfigCmd.hs b/src/Stack/ConfigCmd.hs
--- a/src/Stack/ConfigCmd.hs
+++ b/src/Stack/ConfigCmd.hs
@@ -25,7 +25,7 @@
 import qualified Options.Applicative as OA
 import qualified Options.Applicative.Types as OA
 import           Options.Applicative.Builder.Extra
-import           Pantry (completeSnapshotLocation, loadSnapshot)
+import           Pantry (loadSnapshot)
 import           Path
 import qualified RIO.Map as Map
 import           RIO.Process (envVarsL)
diff --git a/src/Stack/Constants.hs b/src/Stack/Constants.hs
--- a/src/Stack/Constants.hs
+++ b/src/Stack/Constants.hs
@@ -19,7 +19,6 @@
     ,inNixShellEnvVar
     ,stackProgNameUpper
     ,wiredInPackages
-    ,ghcjsBootPackages
     ,cabalPackageName
     ,implicitGlobalProjectDirDeprecated
     ,implicitGlobalProjectDir
@@ -169,7 +168,7 @@
 --
 -- Deprecated since stack-1.1.0.
 --
--- TODO: Remove occurences of this variable and use 'stackRootOptionName' only
+-- TODO: Remove occurrences of this variable and use 'stackRootOptionName' only
 -- after an appropriate deprecation period.
 deprecatedStackRootOptionName :: String
 deprecatedStackRootOptionName = "global-stack-root"
@@ -202,53 +201,6 @@
       , "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 :: Set PackageName
-ghcjsBootPackages =
-    maybe (error "Parse error in ghcjsBootPackages") Set.fromList mparsed
-  where
-    mparsed = mapM 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 =
@@ -305,11 +257,9 @@
 platformVariantEnvVar :: String
 platformVariantEnvVar = stackProgNameUpper ++ "_PLATFORM_VARIANT"
 
--- | Provides --ghc-options for 'Ghc', and similarly, --ghcjs-options
--- for 'Ghcjs'.
+-- | Provides --ghc-options for 'Ghc'
 compilerOptionsCabalFlag :: WhichCompiler -> String
 compilerOptionsCabalFlag Ghc = "--ghc-options"
-compilerOptionsCabalFlag Ghcjs = "--ghcjs-options"
 
 -- | The flag to pass to GHC when we want to force its output to be
 -- colorized.
diff --git a/src/Stack/Constants/Config.hs b/src/Stack/Constants/Config.hs
--- a/src/Stack/Constants/Config.hs
+++ b/src/Stack/Constants/Config.hs
@@ -4,11 +4,13 @@
 module Stack.Constants.Config
   ( distDirFromDir
   , rootDistDirFromDir
+  , setupConfigFromDir
   , workDirFromDir
   , distRelativeDir
   , imageStagingDir
   , projectDockerSandboxDir
   , configCabalMod
+  , configSetupConfigMod
   , buildCachesDir
   , testSuccessFile
   , testBuiltFile
@@ -21,7 +23,6 @@
 
 import Stack.Prelude
 import Stack.Constants
-import Stack.Types.Compiler
 import Stack.Types.Config
 import Path
 
@@ -75,6 +76,15 @@
         (</> $(mkRelFile "stack-cabal-mod"))
         (distDirFromDir dir)
 
+-- | The filename used for modification check of setup-config
+configSetupConfigMod :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
+                     => Path Abs Dir      -- ^ Package directory.
+                     -> m (Path Abs File)
+configSetupConfigMod dir =
+    liftM
+        (</> $(mkRelFile "stack-setup-config-mod"))
+        (distDirFromDir dir)
+
 -- | Directory for HPC work.
 hpcDirFromDir
     :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
@@ -89,6 +99,14 @@
 hpcRelativeDir =
     liftM (</> $(mkRelDir "hpc")) distRelativeDir
 
+-- | Package's setup-config storing Cabal configuration
+setupConfigFromDir :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
+                   => Path Abs Dir
+                   -> m (Path Abs File)
+setupConfigFromDir fp = do
+    dist <- distDirFromDir fp
+    return $ dist </> $(mkRelFile "setup-config")
+
 -- | Package's build artifacts directory.
 distDirFromDir :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
                => Path Abs Dir
@@ -130,11 +148,9 @@
 distRelativeDir = do
     cabalPkgVer <- view cabalVersionL
     platform <- platformGhcRelDir
-    wc <- view $ actualCompilerVersionL.to whichCompiler
-    -- Cabal version, suffixed with "_ghcjs" if we're using GHCJS.
+    -- Cabal version
     envDir <-
         parseRelDir $
-        (if wc == Ghcjs then (++ "_ghcjs") else id) $
         packageIdentifierString $
         PackageIdentifier cabalPackageName cabalPkgVer
     platformAndCabal <- useShaPathOnWindows (platform </> envDir)
diff --git a/src/Stack/Coverage.hs b/src/Stack/Coverage.hs
--- a/src/Stack/Coverage.hs
+++ b/src/Stack/Coverage.hs
@@ -46,6 +46,15 @@
 import           Trace.Hpc.Tix
 import           Web.Browser (openBrowser)
 
+newtype CoverageException = NonTestSuiteTarget PackageName deriving Typeable
+
+instance Exception CoverageException
+instance Show CoverageException where
+    show (NonTestSuiteTarget name) = 
+        "Can't specify anything except test-suites as hpc report targets (" ++
+        packageNameString name ++
+        " is used with a non test-suite target)"
+
 -- | Invoked at the beginning of running with "--coverage"
 deleteHpcReports :: HasEnvConfig env => RIO env ()
 deleteHpcReports = do
@@ -235,10 +244,8 @@
                              case nc of
                                  CTest testName ->
                                      liftM (pkgPath </>) $ parseRelFile (T.unpack testName ++ "/" ++ 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)"
+                                 _ -> throwIO $ NonTestSuiteTarget name
+                                     
                      TargetAll PTProject -> do
                          pkgPath <- hpcPkgPath name
                          exists <- doesDirExist pkgPath
diff --git a/src/Stack/Docker.hs b/src/Stack/Docker.hs
--- a/src/Stack/Docker.hs
+++ b/src/Stack/Docker.hs
@@ -39,8 +39,8 @@
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
 import           Data.Time (UTCTime)
-import           Data.Version (showVersion)
-import           Distribution.Version (mkVersion)
+import qualified Data.Version (showVersion, parseVersion)
+import           Distribution.Version (mkVersion, mkVersion')
 import           Path
 import           Path.Extra (toFilePathNoTrailingSep)
 import           Path.IO hiding (canonicalizePath)
@@ -55,12 +55,12 @@
 import           Stack.Types.Docker
 import           System.Environment (getEnv,getEnvironment,getProgName,getArgs,getExecutablePath)
 import qualified System.FilePath as FP
-import           System.IO (stderr,stdin)
 import           System.IO.Error (isDoesNotExistError)
 import           System.IO.Unsafe (unsafePerformIO)
 import qualified System.PosixCompat.User as User
 import qualified System.PosixCompat.Files as Files
 import           System.Terminal (hIsTerminalDeviceOrMinTTY)
+import           Text.ParserCombinators.ReadP (readP_to_S)
 import           RIO.Process
 
 #ifndef WINDOWS
@@ -90,7 +90,7 @@
             else return Nothing
     args <-
         fmap
-            (["--" ++ reExecArgName ++ "=" ++ showVersion Meta.version
+            (["--" ++ reExecArgName ++ "=" ++ Data.Version.showVersion Meta.version
              ,"--" ++ dockerEntrypointArgName
              ,show DockerEntrypoint{..}] ++)
             (liftIO getArgs)
@@ -151,7 +151,17 @@
         exePath <- ensureDockerStackExe dockerContainerPlatform
         cmdArgs args exePath
     cmdArgs args exePath = do
+        -- MSS 2020-04-21 previously used replaceExtension, but semantics changed in path 0.7
+        -- In any event, I'm not even sure _why_ we need to drop a file extension here
+        -- Originally introduced here: https://github.com/commercialhaskell/stack/commit/6218dadaf5fd7bf312bb1bd0db63b4784ba78cb2
+#if MIN_VERSION_path(0, 7, 0)
+        let exeBase =
+              case splitExtension exePath of
+                Left _ -> exePath
+                Right (x, _) -> x
+#else
         exeBase <- exePath -<.> ""
+#endif
         let mountPath = hostBinDir FP.</> toFilePath (filename exeBase)
         return (mountPath, args, [], [Mount (toFilePath exePath) mountPath])
 
@@ -181,6 +191,7 @@
          bamboo = lookup "bamboo_buildKey" env
          jenkins = lookup "JENKINS_HOME" env
          msshAuthSock = lookup "SSH_AUTH_SOCK" env
+         mstackYaml = lookup "STACK_YAML" env
          muserEnv = lookup "USER" env
          isRemoteDocker = maybe False (isPrefixOf "tcp://") dockerHost
      image <- either throwIO pure (dockerImage docker)
@@ -262,6 +273,11 @@
             Just sshAuthSock ->
               ["-e","SSH_AUTH_SOCK=" ++ sshAuthSock
               ,"-v",sshAuthSock ++ ":" ++ sshAuthSock]
+         ,case mstackYaml of
+            Nothing -> []
+            Just stackYaml ->
+              ["-e","STACK_YAML=" ++ stackYaml
+              ,"-v",stackYaml++ ":" ++ stackYaml ++ ":ro"]
            -- Disable the deprecated entrypoint in FP Complete-generated images
          ,["--entrypoint=/usr/bin/env"
              | isJust (lookupImageEnv oldSandboxIdEnvVar imageEnvVars) &&
@@ -399,7 +415,7 @@
      dockerVersionOut <- readDockerProcess ["--version"]
      case words (decodeUtf8 dockerVersionOut) of
        (_:_:v:_) ->
-         case parseVersion (stripVersion v) of
+         case fmap mkVersion' $ parseVersion' $ stripVersion v of
            Just v'
              | v' < minimumDockerVersion ->
                throwIO (DockerTooOldException minimumDockerVersion v')
@@ -414,6 +430,9 @@
   where minimumDockerVersion = mkVersion [1, 6, 0]
         prohibitedDockerVersions = []
         stripVersion v = takeWhile (/= '-') (dropWhileEnd (not . isDigit) v)
+        -- version is parsed by Data.Version provided code to avoid
+        -- Cabal's Distribution.Version lack of support for leading zeros in version
+        parseVersion' = fmap fst . listToMaybe . reverse . readP_to_S Data.Version.parseVersion
 
 -- | Remove the project's Docker sandbox.
 reset :: HasConfig env => Bool -> RIO env ()
diff --git a/src/Stack/Dot.hs b/src/Stack/Dot.hs
--- a/src/Stack/Dot.hs
+++ b/src/Stack/Dot.hs
@@ -9,11 +9,15 @@
                  ,DotOpts(..)
                  ,DotPayload(..)
                  ,ListDepsOpts(..)
+                 ,ListDepsFormat(..)
+                 ,ListDepsFormatOpts(..)
                  ,resolveDependencies
                  ,printGraph
                  ,pruneGraph
                  ) where
 
+import           Data.Aeson
+import qualified Data.ByteString.Lazy.Char8 as LBC8
 import qualified Data.Foldable as F
 import qualified Data.Sequence as Seq
 import qualified Data.Set as Set
@@ -26,6 +30,7 @@
 import qualified Distribution.SPDX.License as SPDX
 import           Distribution.License (License(BSD3), licenseFromSPDX)
 import           Distribution.Types.PackageName (mkPackageName)
+import qualified Path
 import           RIO.PrettyPrint (HasTerm (..), HasStylesUpdate (..))
 import           RIO.Process (HasProcessContext (..))
 import           Stack.Build (loadPackage)
@@ -33,7 +38,6 @@
 import           Stack.Build.Source
 import           Stack.Constants
 import           Stack.Package
-import           Stack.PackageDump (DumpPackage(..))
 import           Stack.Prelude hiding (Display (..), pkgName, loadPackage)
 import qualified Stack.Prelude (pkgName)
 import           Stack.Runners
@@ -67,15 +71,21 @@
     -- ^ Use global hints instead of relying on an actual GHC installation.
     }
 
+data ListDepsFormatOpts = ListDepsFormatOpts { listDepsSep :: !Text
+                                             -- ^ Separator between the package name and details.
+                                             , listDepsLicense :: !Bool
+                                             -- ^ Print dependency licenses instead of versions.
+                                             }
+
+data ListDepsFormat = ListDepsText ListDepsFormatOpts
+                    | ListDepsTree ListDepsFormatOpts
+                    | ListDepsJSON
+
 data ListDepsOpts = ListDepsOpts
-    { listDepsDotOpts :: !DotOpts
+    { listDepsFormat :: !ListDepsFormat
+    -- ^ Format of printing dependencies
+    , listDepsDotOpts :: !DotOpts
     -- ^ The normal dot options.
-    , listDepsSep :: !Text
-    -- ^ Separator between the package name and details.
-    , listDepsLicense :: !Bool
-    -- ^ Print dependency licenses instead of versions.
-    , listDepsTree :: !Bool
-    -- ^ Print dependency tree.
     }
 
 -- | Visualize the project's dependencies as a graphviz graph
@@ -90,6 +100,8 @@
   -- ^ The package version.
   , payloadLicense :: Maybe (Either SPDX.License License)
   -- ^ The license the package was released under.
+  , payloadLocation :: Maybe PackageLocation
+  -- ^ The location of the package.
   } deriving (Eq, Show)
 
 -- | Create the dependency graph and also prune it as specified in the dot
@@ -131,10 +143,11 @@
           -- Skip packages that can't be loaded - see
           -- https://github.com/commercialhaskell/stack/issues/2967
           | name `elem` [mkPackageName "rts", mkPackageName "ghc"] =
-              return (Set.empty, DotPayload (Just version) (Just $ Right BSD3))
-          | otherwise = fmap (packageAllDeps &&& makePayload) (loadPackage loc flags ghcOptions cabalConfigOpts)
+              return (Set.empty, DotPayload (Just version) (Just $ Right BSD3) Nothing)
+          | otherwise =
+              fmap (packageAllDeps &&& makePayload loc) (loadPackage loc flags ghcOptions cabalConfigOpts)
   resolveDependencies (dotDependencyDepth dotOpts) graph depLoader
-  where makePayload pkg = DotPayload (Just $ packageVersion pkg) (Just $ packageLicense pkg)
+  where makePayload loc pkg = DotPayload (Just $ packageVersion pkg) (Just $ packageLicense pkg) (Just $ PLImmutable loc)
 
 listDependencies
   :: ListDepsOpts
@@ -142,14 +155,53 @@
 listDependencies opts = do
   let dotOpts = listDepsDotOpts opts
   (pkgs, resultGraph) <- createPrunedDependencyGraph dotOpts
-  if listDepsTree opts then
-    do
-      liftIO $ Text.putStrLn "Packages"
-      liftIO $ printTree opts 0 [] (treeRoots opts pkgs) resultGraph
-    else
-      void (Map.traverseWithKey go (snd <$> resultGraph))
-      where go name payload = liftIO $ Text.putStrLn $ listDepsLine opts name payload
+  liftIO $ case listDepsFormat opts of
+      ListDepsTree treeOpts -> Text.putStrLn "Packages" >> printTree treeOpts dotOpts 0 [] (treeRoots opts pkgs) resultGraph
+      ListDepsJSON -> printJSON pkgs resultGraph
+      ListDepsText textOpts -> void (Map.traverseWithKey go (snd <$> resultGraph))
+        where go name payload = Text.putStrLn $ listDepsLine textOpts name payload
 
+data DependencyTree = DependencyTree (Set PackageName) (Map PackageName (Set PackageName, DotPayload))
+
+instance ToJSON DependencyTree where
+  toJSON (DependencyTree _ dependencyMap) =
+    toJSON $ foldToList dependencyToJSON dependencyMap
+
+foldToList :: (k -> a -> b) -> Map k a -> [b]
+foldToList f = Map.foldrWithKey (\k a bs -> bs ++ [f k a]) []
+
+dependencyToJSON :: PackageName -> (Set PackageName, DotPayload) -> Value
+dependencyToJSON pkg (deps, payload) =  let fieldsAlwaysPresent = [ "name" .= packageNameString pkg
+                                                                  , "license" .= licenseText payload
+                                                                  , "version" .= versionText payload
+                                                                  , "dependencies" .= Set.map packageNameString deps
+                                                                  ]
+                                            loc = catMaybes [("location" .=) . pkgLocToJSON <$> payloadLocation payload]
+                                        in object $ fieldsAlwaysPresent ++ loc
+
+pkgLocToJSON :: PackageLocation -> Value
+pkgLocToJSON (PLMutable (ResolvedPath _ dir)) = object [ "type" .= ("project package" :: Text)
+                                              , "url" .= ("file://" ++ Path.toFilePath dir)]
+pkgLocToJSON (PLImmutable (PLIHackage pkgid _ _)) = object [ "type" .= ("hackage" :: Text)
+                                                  , "url" .= ("https://hackage.haskell.org/package/" ++ display pkgid)]
+pkgLocToJSON (PLImmutable (PLIArchive archive _)) = let url = case archiveLocation archive of
+                                                                ALUrl u -> u
+                                                                ALFilePath (ResolvedPath _ path) -> Text.pack $ "file://" ++ Path.toFilePath path
+                                                    in object [ "type" .= ("archive" :: Text)
+                                                              , "url" .= url ]
+pkgLocToJSON (PLImmutable (PLIRepo repo _)) = object [ "type" .= case repoType repo of
+                                                                   RepoGit -> "git" :: Text
+                                                                   RepoHg -> "hg" :: Text
+                                                     , "url" .= repoUrl repo
+                                                     , "commit" .= repoCommit repo
+                                                     , "subdir" .= repoSubdir repo
+                                                     ]
+
+printJSON :: Set PackageName
+          -> Map PackageName (Set PackageName, DotPayload)
+          -> IO ()
+printJSON pkgs dependencyMap = LBC8.putStrLn $ encode $ DependencyTree pkgs dependencyMap
+
 treeRoots :: ListDepsOpts -> Set PackageName -> Set PackageName
 treeRoots opts projectPackages' =
   let targets = dotTargets $ listDepsDotOpts opts
@@ -157,13 +209,14 @@
         then projectPackages'
         else Set.fromList $ map (mkPackageName . Text.unpack) targets
 
-printTree :: ListDepsOpts
+printTree :: ListDepsFormatOpts
+          -> DotOpts
           -> Int
           -> [Int]
           -> Set PackageName
           -> Map PackageName (Set PackageName, DotPayload)
           -> IO ()
-printTree opts depth remainingDepsCounts packages dependencyMap =
+printTree opts dotOpts depth remainingDepsCounts packages dependencyMap =
   F.sequence_ $ Seq.mapWithIndex go (toSeq packages)
   where
     toSeq = Seq.fromList . Set.toList
@@ -171,22 +224,23 @@
                      in
                       case Map.lookup name dependencyMap of
                         Just (deps, payload) -> do
-                          printTreeNode opts depth newDepsCounts deps payload name
-                          if Just depth == dotDependencyDepth (listDepsDotOpts opts)
+                          printTreeNode opts dotOpts depth newDepsCounts deps payload name
+                          if Just depth == dotDependencyDepth dotOpts
                              then return ()
-                             else printTree opts (depth + 1) newDepsCounts deps dependencyMap
+                             else printTree opts dotOpts (depth + 1) newDepsCounts deps dependencyMap
                         -- TODO: Define this behaviour, maybe return an error?
                         Nothing -> return ()
 
-printTreeNode :: ListDepsOpts
+printTreeNode :: ListDepsFormatOpts
+              -> DotOpts
               -> Int
               -> [Int]
               -> Set PackageName
               -> DotPayload
               -> PackageName
               -> IO ()
-printTreeNode opts depth remainingDepsCounts deps payload name =
-  let remainingDepth = fromMaybe 999 (dotDependencyDepth (listDepsDotOpts opts)) - depth
+printTreeNode opts dotOpts depth remainingDepsCounts deps payload name =
+  let remainingDepth = fromMaybe 999 (dotDependencyDepth dotOpts) - depth
       hasDeps = not $ null deps
    in Text.putStrLn $ treeNodePrefix "" remainingDepsCounts hasDeps  remainingDepth  <> " " <> listDepsLine opts name payload
 
@@ -201,15 +255,21 @@
 treeNodePrefix t (0:ns) d remainingDepth = treeNodePrefix (t <> "  ") ns d remainingDepth
 treeNodePrefix t (_:ns) d remainingDepth = treeNodePrefix (t <> "│ ") ns d remainingDepth
 
-listDepsLine :: ListDepsOpts -> PackageName -> DotPayload -> Text
+listDepsLine :: ListDepsFormatOpts -> PackageName -> DotPayload -> Text
 listDepsLine opts name payload = Text.pack (packageNameString name) <> listDepsSep opts <> payloadText opts payload
 
-payloadText :: ListDepsOpts -> DotPayload -> Text
+payloadText :: ListDepsFormatOpts -> DotPayload -> Text
 payloadText opts payload =
   if listDepsLicense opts
-    then maybe "<unknown>" (Text.pack . display . either licenseFromSPDX id) (payloadLicense payload)
-    else maybe "<unknown>" (Text.pack . display) (payloadVersion payload)
+    then licenseText payload
+    else versionText payload
 
+licenseText :: DotPayload -> Text
+licenseText payload = maybe "<unknown>" (Text.pack . display . either licenseFromSPDX id) (payloadLicense payload)
+
+versionText :: DotPayload -> Text
+versionText payload = maybe "<unknown>" (Text.pack . display) (payloadVersion payload)
+
 -- | @pruneGraph dontPrune toPrune graph@ prunes all packages in
 -- @graph@ with a name in @toPrune@ and removes resulting orphans
 -- unless they are in @dontPrune@
@@ -277,7 +337,7 @@
       where
         loadDeps pp = do
           pkg <- loadCommonPackage (ppCommon pp)
-          pure (packageAllDeps pkg, payloadFromLocal pkg)
+          pure (packageAllDeps pkg, payloadFromLocal pkg Nothing)
 
     dependencyDeps =
       loadDeps <$> Map.lookup pkgName (smDeps sourceMap)
@@ -285,7 +345,7 @@
         loadDeps DepPackage{dpLocation=PLMutable dir} = do
               pp <- mkProjectPackage YesPrintWarnings dir False
               pkg <- loadCommonPackage (ppCommon pp)
-              pure (packageAllDeps pkg, payloadFromLocal pkg)
+              pure (packageAllDeps pkg, payloadFromLocal pkg (Just $ PLMutable dir))
 
         loadDeps dp@DepPackage{dpLocation=PLImmutable loc} = do
           let common = dpCommon dp
@@ -313,21 +373,23 @@
     noDepsErr = error ("Invariant violated: The '" ++ packageNameString pkgName
                 ++ "' package was not found in any of the dependency sources")
 
-    payloadFromLocal pkg = DotPayload (Just $ packageVersion pkg) (Just $ packageLicense pkg)
-    payloadFromDump dp = DotPayload (Just $ pkgVersion $ dpPackageIdent dp) (Right <$> dpLicense dp)
+    payloadFromLocal pkg loc = DotPayload (Just $ packageVersion pkg) (Just $ packageLicense pkg) loc
+    payloadFromDump dp = DotPayload (Just $ pkgVersion $ dpPackageIdent dp) (Right <$> dpLicense dp) Nothing
 
 -- | Resolve the direct (depth 0) external dependencies of the given local packages (assumed to come from project packages)
 projectPackageDependencies :: DotOpts -> [LocalPackage] -> [(PackageName, (Set PackageName, DotPayload))]
 projectPackageDependencies dotOpts locals =
     map (\lp -> let pkg = localPackageToPackage lp
-                 in (packageName pkg, (deps pkg, lpPayload pkg)))
+                    pkgDir = Path.parent $ lpCabalFile lp
+                    loc = PLMutable $ ResolvedPath (RelFilePath "N/A") pkgDir
+                 in (packageName pkg, (deps pkg, lpPayload pkg loc)))
         locals
   where deps pkg =
           if dotIncludeExternal dotOpts
             then Set.delete (packageName pkg) (packageAllDeps pkg)
             else Set.intersection localNames (packageAllDeps pkg)
         localNames = Set.fromList $ map (packageName . lpPackage) locals
-        lpPayload pkg = DotPayload (Just $ packageVersion pkg) (Just $ packageLicense pkg)
+        lpPayload pkg loc = DotPayload (Just $ packageVersion pkg) (Just $ packageLicense pkg) (Just loc)
 
 -- | Print a graphviz graph of the edges in the Map and highlight the given local packages
 printGraph :: (Applicative m, MonadIO m)
@@ -405,8 +467,11 @@
       bconfig <- view buildConfigL
       globals <- globalsFromHints $ smwCompiler $ bcSMWanted bconfig
       fakeGhcPkgId <- parseGhcPkgId "ignored"
+      actual <- either throwIO pure $
+                wantedToActual $ smwCompiler $
+                bcSMWanted bconfig
       let smActual = SMActual
-            { smaCompiler = wantedToActual $ smwCompiler $ bcSMWanted bconfig
+            { smaCompiler = actual
             , smaProject = smwProject $ bcSMWanted bconfig
             , smaDeps = smwDeps $ bcSMWanted bconfig
             , smaGlobal = Map.mapWithKey toDump globals
diff --git a/src/Stack/FileWatch.hs b/src/Stack/FileWatch.hs
--- a/src/Stack/FileWatch.hs
+++ b/src/Stack/FileWatch.hs
@@ -13,18 +13,18 @@
 import GHC.IO.Exception
 import Path
 import System.FSNotify
-import System.IO (hPutStrLn, getLine)
-import System.Terminal
+import System.IO (getLine)
+import RIO.PrettyPrint hiding (line)
 
 fileWatch
-  :: Handle
-  -> ((Set (Path Abs File) -> IO ()) -> RIO env ())
+  :: (HasLogFunc env, HasTerm env)
+  => ((Set (Path Abs File) -> IO ()) -> RIO env ())
   -> RIO env ()
 fileWatch = fileWatchConf defaultConfig
 
 fileWatchPoll
-  :: Handle
-  -> ((Set (Path Abs File) -> IO ()) -> RIO env ())
+  :: (HasLogFunc env, HasTerm env)
+  => ((Set (Path Abs File) -> IO ()) -> RIO env ())
   -> RIO env ()
 fileWatchPoll = fileWatchConf $ defaultConfig { confUsePolling = True }
 
@@ -33,18 +33,11 @@
 -- 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
-  -> Handle
+  :: (HasLogFunc env, HasTerm env)
+  => WatchConfig
   -> ((Set (Path Abs File) -> IO ()) -> RIO env ())
   -> RIO env ()
-fileWatchConf cfg out inner = withRunInIO $ \run -> withManagerConf cfg $ \manager -> do
-    let putLn = hPutStrLn out -- FIXME
-    outputIsTerminal <- hIsTerminalDeviceOrMinTTY out
-    let withColor color str = putLn $ do
-            if outputIsTerminal
-            then concat [color, str, reset]
-            else str
-
+fileWatchConf cfg inner = withRunInIO $ \run -> withManagerConf cfg $ \manager -> do
     allFiles <- newTVarIO Set.empty
     dirtyVar <- newTVarIO True
     watchVar <- newTVarIO Map.empty
@@ -92,32 +85,31 @@
     let watchInput = do
             line <- getLine
             unless (line == "quit") $ do
-                case line of
+                run $ case line of
                     "help" -> do
-                        putLn ""
-                        putLn "help: display this help"
-                        putLn "quit: exit"
-                        putLn "build: force a rebuild"
-                        putLn "watched: display watched files"
+                        logInfo ""
+                        logInfo "help: display this help"
+                        logInfo "quit: exit"
+                        logInfo "build: force a rebuild"
+                        logInfo "watched: display watched files"
                     "build" -> atomically $ writeTVar dirtyVar True
                     "watched" -> do
                         watch <- readTVarIO allFiles
-                        mapM_ putLn (Set.toList watch)
+                        mapM_ (logInfo . fromString) (Set.toList watch)
                     "" -> atomically $ writeTVar dirtyVar True
-                    _ -> putLn $ concat
-                        [ "Unknown command: "
-                        , show line
-                        , ". Try 'help'"
-                        ]
+                    _ -> logInfo $
+                        "Unknown command: " <>
+                        displayShow line <>
+                        ". Try 'help'"
 
                 watchInput
 
-    race_ watchInput $ forever $ do
+    race_ watchInput $ run $ forever $ do
         atomically $ do
             dirty <- readTVar dirtyVar
             check dirty
 
-        eres <- tryAny $ run $ inner setWatched
+        eres <- tryAny $ inner setWatched
 
         -- Clear dirtiness flag after the build to avoid an infinite
         -- loop caused by the build itself triggering dirtiness. This
@@ -127,17 +119,13 @@
         -- https://github.com/commercialhaskell/stack/issues/822
         atomically $ writeTVar dirtyVar False
 
-        case eres of
-            Left e -> do
-                let color = case fromException e of
-                        Just ExitSuccess -> green
-                        _ -> red
-                withColor color $ show e
-            _ -> withColor green "Success! Waiting for next file change."
-
-        putLn "Type help for available commands. Press enter to force a rebuild."
+        prettyInfo $
+          case eres of
+            Left e ->
+                let theStyle = case fromException e of
+                        Just ExitSuccess -> Good
+                        _ -> Error
+                 in style theStyle $ fromString $ show e
+            _ -> style Good "Success! Waiting for next file change."
 
-green, red, reset :: String
-green = "\ESC[32m"
-red = "\ESC[31m"
-reset = "\ESC[0m"
+        logInfo "Type help for available commands. Press enter to force a rebuild."
diff --git a/src/Stack/Freeze.hs b/src/Stack/Freeze.hs
deleted file mode 100644
--- a/src/Stack/Freeze.hs
+++ /dev/null
@@ -1,79 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Stack.Freeze
-    ( freeze
-    , FreezeOpts (..)
-    , FreezeMode (..)
-    ) where
-
-import           Data.Aeson ((.=), object)
-import qualified Data.Yaml as Yaml
-import           RIO.Process
-import qualified RIO.ByteString as B
-import           Stack.Prelude
-import           Stack.Types.Config
-
-data FreezeMode = FreezeProject | FreezeSnapshot
-
-newtype FreezeOpts = FreezeOpts
-    { freezeMode :: FreezeMode
-    }
-
-freeze :: HasEnvConfig env => FreezeOpts -> RIO env ()
-freeze (FreezeOpts mode) = do
-  mproject <- view $ configL.to configProject
-  let warn = logWarn "No project was found: nothing to freeze"
-  case mproject of
-    PCProject (p, _) -> doFreeze p mode
-    PCGlobalProject -> warn
-    PCNoProject _ -> warn
-
-doFreeze ::
-       (HasProcessContext env, HasLogFunc env, HasPantryConfig env)
-    => Project
-    -> FreezeMode
-    -> RIO env ()
-doFreeze p FreezeProject = do
-  let deps = projectDependencies p
-      resolver = projectResolver p
-      completePackageLocation' pl =
-        case pl of
-          RPLImmutable pli -> PLImmutable <$> completePackageLocation pli
-          RPLMutable m -> pure $ PLMutable m
-  resolver' <- completeSnapshotLocation resolver
-  deps' <- mapM completePackageLocation' deps
-  let rawCompleted = map toRawPL deps'
-      rawResolver = toRawSL resolver'
-  if rawCompleted == deps && rawResolver == resolver
-  then
-    logInfo "No freezing is required for this project"
-  else do
-    logInfo "# Fields not mentioned below do not need to be updated"
-
-    if rawResolver == resolver
-      then logInfo "# No update to resolver is needed"
-      else do
-        logInfo "# Frozen version of resolver"
-        B.putStr $ Yaml.encode $ object ["resolver" .= rawResolver]
-
-    if rawCompleted == deps
-      then logInfo "# No update to extra-deps is needed"
-      else do
-        logInfo "# Frozen version of extra-deps"
-        B.putStr $ Yaml.encode $ object ["extra-deps" .= rawCompleted]
-
-doFreeze p FreezeSnapshot = do
-  resolver <- completeSnapshotLocation $ projectResolver p
-  result <- loadSnapshotLayer resolver
-  case result of
-    Left _wc ->
-      logInfo "No freezing is required for compiler resolver"
-    Right snap -> do
-      snap' <- completeSnapshotLayer snap
-      let rawCompleted = toRawSnapshotLayer snap'
-      if rawCompleted == snap
-        then
-        logInfo "No freezing is required for the snapshot of this project"
-        else
-        liftIO $ B.putStr $ Yaml.encode snap'
diff --git a/src/Stack/GhcPkg.hs b/src/Stack/GhcPkg.hs
--- a/src/Stack/GhcPkg.hs
+++ b/src/Stack/GhcPkg.hs
@@ -18,7 +18,6 @@
 import qualified Data.ByteString.Char8 as S8
 import qualified Data.ByteString.Lazy as BL
 import           Data.List
-import           Data.List.NonEmpty (NonEmpty(..))
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
 import           Path (parent, (</>))
@@ -103,7 +102,6 @@
 -- | Get the environment variable to use for the package DB paths.
 ghcPkgPathEnvVar :: WhichCompiler -> Text
 ghcPkgPathEnvVar Ghc = "GHC_PACKAGE_PATH"
-ghcPkgPathEnvVar Ghcjs = "GHCJS_PACKAGE_PATH"
 
 -- | Get the necessary ghc-pkg flags for setting up the given package database
 packageDbFlags :: [Path Abs Dir] -> [String]
@@ -131,7 +129,8 @@
             Right bs ->
                 fmap (stripCR . T.decodeUtf8) $ listToMaybe $ S8.lines bs
 
--- | unregister list of package ghcids, batching available from GHC 8.0.1,
+-- | unregister list of package ghcids, batching available from GHC 8.2.1,
+-- see https://github.com/commercialhaskell/stack/issues/2662#issuecomment-460342402
 -- using GHC package id where available (from GHC 7.9)
 unregisterGhcPkgIds
   :: (HasProcessContext env, HasLogFunc env)
@@ -145,11 +144,10 @@
         Left e -> logWarn $ displayShow e
         Right _ -> return ()
   where
+    (idents, gids) = partitionEithers $ toList epgids
     args = "unregister" : "--user" : "--force" :
-        concatMap (either
-            (\ident -> [packageIdentifierString ident])
-            (\gid -> ["--ipid", ghcPkgIdString gid]))
-            epgids
+        map packageIdentifierString idents ++
+        if null gids then [] else "--ipid" : map ghcPkgIdString gids
 
 -- | Get the value for GHC_PACKAGE_PATH
 mkGhcPackagePath :: Bool -> Path Abs Dir -> Path Abs Dir -> [Path Abs Dir] -> Path Abs Dir -> Text
diff --git a/src/Stack/Ghci/Script.hs b/src/Stack/Ghci/Script.hs
--- a/src/Stack/Ghci/Script.hs
+++ b/src/Stack/Ghci/Script.hs
@@ -19,7 +19,7 @@
 import qualified Data.Set as S
 import           Path
 import           Stack.Prelude
-import           System.IO (BufferMode (..), hSetBinaryMode)
+import           System.IO (hSetBinaryMode)
 
 import           Distribution.ModuleName hiding (toFilePath)
 
diff --git a/src/Stack/Hoogle.hs b/src/Stack/Hoogle.hs
--- a/src/Stack/Hoogle.hs
+++ b/src/Stack/Hoogle.hs
@@ -11,6 +11,7 @@
 import qualified Data.ByteString.Lazy.Char8 as BL8
 import           Data.Char (isSpace)
 import qualified Data.Text as T
+import           Distribution.PackageDescription (packageDescription, package)
 import           Distribution.Types.PackageName (mkPackageName)
 import           Distribution.Version (mkVersion)
 import           Lens.Micro ((?~))
@@ -20,8 +21,13 @@
 import           Stack.Build.Target (NeedTargets(NeedTargets))
 import           Stack.Runners
 import           Stack.Types.Config
+import           Stack.Types.SourceMap
+import qualified RIO.Map as Map
 import           RIO.Process
 
+-- | Helper type to duplicate log messages
+data Muted = Muted | NotMuted
+
 -- | Hoogle command.
 hoogleCmd :: ([String],Bool,Bool,Bool) -> RIO Runner ()
 hoogleCmd (args,setup,rebuild,startServer) =
@@ -74,52 +80,67 @@
     hoogleMinVersion = mkVersion [5, 0]
     hoogleMinIdent =
         PackageIdentifier hooglePackageName hoogleMinVersion
-    installHoogle :: RIO EnvConfig ()
-    installHoogle = do
-        hooglePackageIdentifier <- do
-          mversion <- getLatestHackageVersion YesRequireHackageIndex hooglePackageName UsePreferredVersions
-
-          -- FIXME For a while, we've been following the logic of
-          -- taking the latest Hoogle version available. However, we
-          -- may want to instead grab the version of Hoogle present in
-          -- the snapshot current being used instead.
-          pure $ fromMaybe (Left hoogleMinIdent) $ do
-            pir@(PackageIdentifierRevision _ ver _) <- mversion
-            guard $ ver >= hoogleMinVersion
-            Just $ Right pir
-
-        case hooglePackageIdentifier of
-            Left{} -> logInfo $
-              "Minimum " <>
-              fromString (packageIdentifierString hoogleMinIdent) <>
-              " is not in your index. Installing the minimum version."
-            Right ident -> logInfo $
-              "Minimum version is " <>
-              fromString (packageIdentifierString hoogleMinIdent) <>
-              ". Found acceptable " <>
-              display ident <>
-              " in your index, installing it."
+    installHoogle :: RIO EnvConfig (Path Abs File)
+    installHoogle = requiringHoogle Muted $ do
+        Stack.Build.build Nothing
+        mhooglePath' <- findExecutable "hoogle"
+        case mhooglePath' of
+            Right hooglePath -> parseAbsFile hooglePath
+            Left _ -> do
+                logWarn "Couldn't find hoogle in path after installing.  This shouldn't happen, may be a bug."
+                bail
+    requiringHoogle :: Muted -> RIO EnvConfig x -> RIO EnvConfig x
+    requiringHoogle muted f = do
+        hoogleTarget <- do
+          sourceMap <- view $ sourceMapL . to smDeps
+          case Map.lookup hooglePackageName sourceMap of
+            Just hoogleDep ->
+              case dpLocation hoogleDep of
+                PLImmutable pli ->
+                  T.pack . packageIdentifierString <$>
+                      restrictMinHoogleVersion muted (packageLocationIdent pli)
+                plm@(PLMutable _) -> do
+                  T.pack . packageIdentifierString . package . packageDescription
+                      <$> loadCabalFile plm
+            Nothing -> do
+              -- not muted because this should happen only once
+              logWarn "No hoogle version was found, trying to install the latest version"
+              mpir <- getLatestHackageVersion YesRequireHackageIndex hooglePackageName UsePreferredVersions
+              let hoogleIdent = case mpir of
+                      Nothing -> hoogleMinIdent
+                      Just (PackageIdentifierRevision _ ver _) ->
+                          PackageIdentifier hooglePackageName ver
+              T.pack . packageIdentifierString <$>
+                  restrictMinHoogleVersion muted hoogleIdent
         config <- view configL
-        menv <- liftIO $ configProcessContextSettings config envSettings
         let boptsCLI = defaultBuildOptsCLI
-                { boptsCLITargets =
-                    pure $
-                    T.pack . packageIdentifierString $
-                    either
-                    id
-                    (\(PackageIdentifierRevision n v _) -> PackageIdentifier n v)
-                    hooglePackageIdentifier
+                { boptsCLITargets =  [hoogleTarget]
                 }
-        runRIO config $ catch -- Also a bit weird
-                 (withEnvConfig
-                      NeedTargets
-                      boptsCLI $
-                      Stack.Build.build Nothing
-                 )
-                 (\(e :: ExitCode) ->
-                       case e of
-                           ExitSuccess -> runRIO menv resetExeCache
-                           _ -> throwIO e)
+        runRIO config $ withEnvConfig NeedTargets boptsCLI f
+    restrictMinHoogleVersion
+      :: HasLogFunc env
+      => Muted -> PackageIdentifier -> RIO env PackageIdentifier
+    restrictMinHoogleVersion muted ident = do
+      if ident < hoogleMinIdent
+      then do
+          muteableLog LevelWarn muted $
+               "Minimum " <>
+               fromString (packageIdentifierString hoogleMinIdent) <>
+               " is not in your index. Installing the minimum version."
+          pure hoogleMinIdent
+      else do
+          muteableLog LevelInfo muted $
+              "Minimum version is " <>
+              fromString (packageIdentifierString hoogleMinIdent) <>
+              ". Found acceptable " <>
+              fromString (packageIdentifierString ident) <>
+              " in your index, requiring its installation."
+          pure ident
+    muteableLog :: HasLogFunc env => LogLevel -> Muted -> Utf8Builder -> RIO env ()
+    muteableLog logLevel muted msg =
+        case muted of
+            Muted -> pure ()
+            NotMuted -> logGeneric "" logLevel msg
     runHoogle :: Path Abs File -> [String] -> RIO EnvConfig ()
     runHoogle hooglePath hoogleArgs = do
         config <- view configL
@@ -139,7 +160,8 @@
     ensureHoogleInPath = do
         config <- view configL
         menv <- liftIO $ configProcessContextSettings config envSettings
-        mhooglePath <- runRIO menv $ findExecutable "hoogle"
+        mhooglePath <- runRIO menv (findExecutable "hoogle") <>
+          requiringHoogle NotMuted (findExecutable "hoogle")
         eres <- case mhooglePath of
             Left _ -> return $ Left "Hoogle isn't installed."
             Right hooglePath -> do
@@ -171,12 +193,6 @@
                 | setup -> do
                     logWarn $ display err <> " Automatically installing (use --no-setup to disable) ..."
                     installHoogle
-                    mhooglePath' <- runRIO menv $ findExecutable "hoogle"
-                    case mhooglePath' of
-                        Right hooglePath -> parseAbsFile hooglePath
-                        Left _ -> do
-                            logWarn "Couldn't find hoogle in path after installing.  This shouldn't happen, may be a bug."
-                            bail
                 | otherwise -> do
                     logWarn $ display err <> " Not installing it due to --no-setup."
                     bail
diff --git a/src/Stack/Init.hs b/src/Stack/Init.hs
--- a/src/Stack/Init.hs
+++ b/src/Stack/Init.hs
@@ -17,7 +17,6 @@
 import qualified Data.HashMap.Strict             as HM
 import qualified Data.IntMap                     as IntMap
 import           Data.List.Extra                 (groupSortOn)
-import           Data.List.NonEmpty              (NonEmpty (..))
 import qualified Data.List.NonEmpty              as NonEmpty
 import qualified Data.Map.Strict                 as Map
 import qualified Data.Set                        as Set
@@ -116,7 +115,8 @@
           Map.mapMaybe (flip Map.lookup gpdByDir . resolvedAbsolute) rbundle
 
     deps <- for (Map.toList extraDeps) $ \(n, v) ->
-      PLImmutable <$> completePackageLocation (RPLIHackage (PackageIdentifierRevision n v CFILatest) Nothing)
+      PLImmutable . cplComplete <$>
+      completePackageLocation (RPLIHackage (PackageIdentifierRevision n v CFILatest) Nothing)
 
     let p = Project
             { projectUserMsg = if userMsg == "" then Nothing else Just userMsg
diff --git a/src/Stack/Lock.hs b/src/Stack/Lock.hs
--- a/src/Stack/Lock.hs
+++ b/src/Stack/Lock.hs
@@ -13,11 +13,11 @@
 import Pantry.Internal.AesonExtended
 import Data.ByteString.Builder (byteString)
 import qualified Data.List.NonEmpty as NE
-import Data.Map (Map)
 import qualified Data.Map as Map
 import qualified Data.Yaml as Yaml
 import Pantry
-import Path (addFileExtension, parent)
+import Path (parent)
+import Path.Extended (addExtension)
 import Path.IO (doesFileExist)
 import Stack.Prelude
 import Stack.SourceMap
@@ -95,7 +95,7 @@
         -> RIO env ( SMWanted, [CompletedPLI]))
     -> RIO env SMWanted
 lockCachedWanted stackFile resolver fillWanted = do
-    lockFile <- liftIO $ addFileExtension "lock" stackFile
+    lockFile <- liftIO $ addExtension ".lock" stackFile
     let getLockExists = doesFileExist lockFile
     lfb <- view lockFileBehaviorL
     readLockFile <-
diff --git a/src/Stack/Ls.hs b/src/Stack/Ls.hs
--- a/src/Stack/Ls.hs
+++ b/src/Stack/Ls.hs
@@ -9,8 +9,7 @@
   , listDependenciesCmd
   ) where
 
-import Control.Exception (Exception, throw)
-import Control.Monad (when)
+import Control.Exception (throw)
 import Data.Aeson
 import Data.Array.IArray ((//), elems)
 import Stack.Prelude hiding (Snapshot (..))
@@ -19,11 +18,10 @@
 import Data.Text hiding (pack, intercalate)
 import qualified Data.Text as T
 import qualified Data.Text.IO as T
-import Data.Typeable (Typeable)
 import qualified Data.Vector as V
 import Network.HTTP.StackClient (httpJSON, addRequestHeader, getResponseBody, parseRequest, hAccept)
 import qualified Options.Applicative as OA
-import Options.Applicative ((<|>), idm)
+import Options.Applicative (idm)
 import Options.Applicative.Builder.Extra (boolFlags)
 import Path
 import RIO.PrettyPrint (useColorL)
diff --git a/src/Stack/New.hs b/src/Stack/New.hs
--- a/src/Stack/New.hs
+++ b/src/Stack/New.hs
@@ -17,7 +17,6 @@
 
 import           Stack.Prelude
 import           Control.Monad.Trans.Writer.Strict
-import           Control.Monad (void)
 import           Data.ByteString.Builder (lazyByteString)
 import qualified Data.ByteString.Lazy as LB
 import           Data.Conduit
@@ -30,9 +29,9 @@
 import qualified Data.Text.Lazy.Encoding as TLE
 import           Data.Time.Calendar
 import           Data.Time.Clock
-import           Network.HTTP.StackClient (DownloadException (..), Request, HttpException,
-                                           getResponseStatusCode, getResponseBody, httpLbs,
-                                           parseRequest, parseUrlThrow, redownload, setGithubHeaders)
+import           Network.HTTP.StackClient (VerifiedDownloadException (..), Request, HttpException,
+                                           getResponseBody, httpLbs, mkDownloadRequest, parseRequest, parseUrlThrow,
+                                           setForceDownload, setGithubHeaders, verifiedDownloadWithProgress)
 import           Path
 import           Path.IO
 import           Stack.Constants
@@ -155,13 +154,16 @@
         downloadTemplate req (templateDir </> rel)
     downloadTemplate :: Request -> Path Abs File -> RIO env Text
     downloadTemplate req path = do
+        let dReq = setForceDownload True $ mkDownloadRequest req
         logIt RemoteTemp
         catch
-          (void $ redownload req path)
+          (void $ do
+            verifiedDownloadWithProgress dReq path (T.pack $ toFilePath path) Nothing
+          )
           (useCachedVersionOrThrow path)
 
         loadLocalFile path
-    useCachedVersionOrThrow :: Path Abs File -> DownloadException -> RIO env ()
+    useCachedVersionOrThrow :: Path Abs File -> VerifiedDownloadException -> RIO env ()
     useCachedVersionOrThrow path exception = do
       exists <- doesFileExist path
 
@@ -318,7 +320,7 @@
     = FailedToLoadTemplate !TemplateName
                            !FilePath
     | FailedToDownloadTemplate !TemplateName
-                               !DownloadException
+                               !VerifiedDownloadException
     | AlreadyExists !(Path Abs Dir)
     | MissingParameters !PackageName !TemplateName !(Set String) !(Path Abs File)
     | InvalidTemplate !TemplateName !String
@@ -337,18 +339,13 @@
         "Failed to load download template " <> T.unpack (templateName name) <>
         " from " <>
         path
-    show (FailedToDownloadTemplate name (RedownloadInvalidResponse _ _ resp)) =
-        case getResponseStatusCode resp of
-            404 ->
-                "That template doesn't exist. Run `stack templates' to discover available templates."
-            code ->
-                "Failed to download template " <> T.unpack (templateName name) <>
-                ": unknown reason, status code was: " <>
-                show code
-
-    show (FailedToDownloadTemplate name (RedownloadHttpError httpError)) =
+    show (FailedToDownloadTemplate name (DownloadHttpError httpError)) =
           "There was an unexpected HTTP error while downloading template " <>
           T.unpack (templateName name) <> ": " <> show httpError
+    show (FailedToDownloadTemplate name _) =
+        "Failed to download template " <> T.unpack (templateName name) <>
+        ": unknown reason"
+
     show (AlreadyExists path) =
         "Directory " <> toFilePath path <> " already exists. Aborting."
     show (MissingParameters name template missingKeys userConfigPath) =
diff --git a/src/Stack/Nix.hs b/src/Stack/Nix.hs
--- a/src/Stack/Nix.hs
+++ b/src/Stack/Nix.hs
@@ -15,7 +15,6 @@
 import           Stack.Prelude
 import qualified Data.Text as T
 import           Data.Version (showVersion)
-import           Lens.Micro (set)
 import           Path.IO
 import qualified Paths_stack as Meta
 import           Stack.Config (getInContainer, withBuildConfig)
diff --git a/src/Stack/Options/BuildParser.hs b/src/Stack/Options/BuildParser.hs
--- a/src/Stack/Options/BuildParser.hs
+++ b/src/Stack/Options/BuildParser.hs
@@ -54,6 +54,11 @@
          (long "only-dependencies" <>
           help
               "Only build packages that are dependencies of targets on the command line") <|>
+     flag'
+         BSOnlyLocals
+         (long "only-locals" <>
+          help
+              "Only build packages in the local database, fail if the build plan includes the snapshot database") <|>
      pure BSAll) <*>
     (flag'
          FileWatch
diff --git a/src/Stack/Options/ConfigParser.hs b/src/Stack/Options/ConfigParser.hs
--- a/src/Stack/Options/ConfigParser.hs
+++ b/src/Stack/Options/ConfigParser.hs
@@ -21,8 +21,8 @@
 configOptsParser currentDir hide0 =
     (\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch
         ghcVariant ghcBuild jobs includes libs overrideGccPath overrideHpack
-        skipGHCCheck skipMsys localBin modifyCodePage allowDifferentUser
-        dumpLogs colorWhen -> mempty
+        skipGHCCheck skipMsys localBin setupInfoLocations modifyCodePage
+        allowDifferentUser dumpLogs colorWhen -> mempty
             { configMonoidStackRoot = stackRoot
             , configMonoidWorkDir = workDir
             , configMonoidBuildOpts = buildOpts
@@ -41,6 +41,7 @@
             , configMonoidOverrideHpack = overrideHpack
             , configMonoidSkipMsys = skipMsys
             , configMonoidLocalBinPath = localBin
+            , configMonoidSetupInfoLocations = setupInfoLocations
             , configMonoidModifyCodePage = modifyCodePage
             , configMonoidAllowDifferentUser = allowDifferentUser
             , configMonoidDumpLogs = dumpLogs
@@ -128,6 +129,11 @@
             <> help "Install binaries to DIR"
             <> hide
              ))
+    <*> many (
+        strOption
+            ( long "setup-info-yaml"
+           <> help "Alternate URL or relative / absolute path for stack dependencies"
+           <> metavar "URL" ))
     <*> firstBoolFlagsTrue
             "modify-code-page"
             "setting the codepage to support UTF-8 (Windows only)"
diff --git a/src/Stack/Options/DotParser.hs b/src/Stack/Options/DotParser.hs
--- a/src/Stack/Options/DotParser.hs
+++ b/src/Stack/Options/DotParser.hs
@@ -7,7 +7,7 @@
 import           Data.List.Split (splitOn)
 import qualified Data.Set as Set
 import qualified Data.Text as T
-import           Distribution.Types.PackageName(PackageName, mkPackageName)
+import           Distribution.Types.PackageName(mkPackageName)
 import           Options.Applicative
 import           Options.Applicative.Builder.Extra
 import           Stack.Dot
@@ -57,23 +57,49 @@
         globalHints = switch (long "global-hints" <>
                               help "Do not require an install GHC; instead, use a hints file for global packages")
 
+separatorParser :: Parser Text
+separatorParser =
+  fmap escapeSep
+  (textOption (long "separator" <>
+                metavar "SEP" <>
+                help ("Separator between package name " <>
+                      "and package version.") <>
+                value " " <>
+                showDefault))
+  where escapeSep sep = T.replace "\\t" "\t" (T.replace "\\n" "\n" sep)
+
+licenseParser :: Parser Bool
+licenseParser = boolFlags False
+                "license"
+                "printing of dependency licenses instead of versions"
+                idm
+
+listDepsFormatOptsParser :: Parser ListDepsFormatOpts
+listDepsFormatOptsParser = ListDepsFormatOpts <$> separatorParser <*> licenseParser
+
+listDepsTreeParser :: Parser ListDepsFormat
+listDepsTreeParser =  ListDepsTree <$> listDepsFormatOptsParser
+
+listDepsTextParser :: Parser ListDepsFormat
+listDepsTextParser = ListDepsText <$> listDepsFormatOptsParser
+
+listDepsJsonParser :: Parser ListDepsFormat
+listDepsJsonParser = pure ListDepsJSON
+
+toListDepsOptsParser :: Parser ListDepsFormat -> Parser ListDepsOpts
+toListDepsOptsParser formatParser = ListDepsOpts
+      <$> formatParser
+      <*> dotOptsParser True
+
+formatSubCommand :: String -> String -> Parser ListDepsFormat -> Mod CommandFields ListDepsOpts
+formatSubCommand cmd desc formatParser =
+  command cmd (info (toListDepsOptsParser formatParser)
+               (progDesc desc))
+
 -- | Parser for arguments to `stack ls dependencies`.
 listDepsOptsParser :: Parser ListDepsOpts
-listDepsOptsParser = ListDepsOpts
-                 <$> dotOptsParser True -- Default for --external is True.
-                 <*> fmap escapeSep
-                     (textOption (long "separator" <>
-                                  metavar "SEP" <>
-                                  help ("Separator between package name " <>
-                                        "and package version.") <>
-                                  value " " <>
-                                  showDefault))
-                 <*> boolFlags False
-                                "license"
-                                "printing of dependency licenses instead of versions"
-                                idm
-                 <*> boolFlags False
-                                "tree"
-                                "printing of dependencies as a tree"
-                                idm
-  where escapeSep sep = T.replace "\\t" "\t" (T.replace "\\n" "\n" sep)
+listDepsOptsParser = subparser
+                     (  formatSubCommand "text" "Print dependencies as text (default)" listDepsTextParser
+                     <> formatSubCommand "tree" "Print dependencies as tree" listDepsTreeParser
+                     <> formatSubCommand "json" "Print dependencies as JSON" listDepsJsonParser
+                     ) <|> toListDepsOptsParser listDepsTextParser
diff --git a/src/Stack/Options/FreezeParser.hs b/src/Stack/Options/FreezeParser.hs
deleted file mode 100644
--- a/src/Stack/Options/FreezeParser.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Stack.Options.FreezeParser where
-
-import           Data.Semigroup ((<>))
-import           Options.Applicative
-import           Stack.Freeze
-
-
--- | Parser for arguments to `stack freeze`
-freezeOptsParser :: Parser FreezeOpts
-freezeOptsParser =
-  FreezeOpts <$> flag FreezeProject FreezeSnapshot
-                 ( long "snapshot"
-                   <> short 's'
-                   <> help "Freeze snapshot definition instead of project's stack.yaml" )
diff --git a/src/Stack/Package.hs b/src/Stack/Package.hs
--- a/src/Stack/Package.hs
+++ b/src/Stack/Package.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -28,7 +29,6 @@
   ) where
 
 import           Data.List (find, isPrefixOf, unzip)
-import           Data.Maybe (maybe)
 import qualified Data.Map.Strict as M
 import qualified Data.Set as S
 import qualified Data.Text as T
@@ -40,6 +40,7 @@
 import qualified Distribution.PackageDescription as D
 import           Distribution.PackageDescription hiding (FlagName)
 import           Distribution.PackageDescription.Parsec
+import           Distribution.Pretty (prettyShow)
 import           Distribution.Simple.Glob (matchDirFileGlob)
 import           Distribution.System (OS (..), Arch, Platform (..))
 import qualified Distribution.Text as D
@@ -47,12 +48,17 @@
 import qualified Distribution.Types.ExeDependency as Cabal
 import           Distribution.Types.ForeignLib
 import qualified Distribution.Types.LegacyExeDependency as Cabal
+import           Distribution.Types.LibraryName (libraryNameString, maybeToLibraryName)
 import           Distribution.Types.MungedPackageName
 import qualified Distribution.Types.UnqualComponentName as Cabal
 import qualified Distribution.Verbosity as D
 import           Distribution.Version (mkVersion, orLaterVersion, anyVersion)
 import qualified HiFileParser as Iface
+#if MIN_VERSION_path(0,7,0)
+import           Path as FL hiding (replaceExtension)
+#else
 import           Path as FL
+#endif
 import           Path.Extra
 import           Path.IO hiding (findFiles)
 import           Stack.Build.Installed
@@ -191,7 +197,7 @@
     subLibNames
       = S.fromList
       $ map (T.pack . Cabal.unUnqualComponentName)
-      $ mapMaybe libName -- this is a design bug in the Cabal API: this should statically be known to exist
+      $ mapMaybe (libraryNameString . libName) -- this is a design bug in the Cabal API: this should statically be known to exist
       $ filter (buildable . libBuildInfo)
       $ subLibraries pkg
 
@@ -202,8 +208,8 @@
       $ foreignLibs pkg
 
     toInternalPackageMungedName
-      = T.pack . unMungedPackageName . computeCompatPackageName (pkgName pkgId)
-      . Just . Cabal.mkUnqualComponentName . T.unpack
+      = T.pack . prettyShow . MungedPackageName (pkgName pkgId)
+      . maybeToLibraryName . Just . Cabal.mkUnqualComponentName . T.unpack
 
     -- Gets all of the modules, files, build files, and data files that
     -- constitute the package. This is primarily used for dirtiness
@@ -248,7 +254,7 @@
         , knownTools
         ])
     msetupDeps = fmap
-        (M.fromList . map (depName &&& depRange) . setupDepends)
+        (M.fromList . map (depPkgName &&& depVerRange) . setupDepends)
         (setupBuildInfo pkg)
 
     asLibrary range = DepValue
@@ -303,7 +309,7 @@
                          (library pkg)
                    , mapMaybe
                          (\sublib -> do
-                            let maybeLib = CInternalLib . T.pack . Cabal.unUnqualComponentName <$> libName sublib
+                            let maybeLib = CInternalLib . T.pack . Cabal.unUnqualComponentName <$> (libraryNameString . libName) sublib
                             flip generate  (libBuildInfo sublib) <$> maybeLib
                           )
                          (subLibraries pkg)
@@ -383,12 +389,9 @@
     pkgs =
         biAddPackages ++
         [ name
-        | Dependency name _ <- targetBuildDepends biBuildInfo
+        | Dependency name _ _ <- targetBuildDepends biBuildInfo -- TODO: cabal 3 introduced multiple public libraries in a single dependency
         , name `notElem` biOmitPackages]
-    ghcOpts = concatMap snd . filter (isGhc . fst) $ options biBuildInfo
-      where
-        isGhc GHC = True
-        isGhc _ = False
+    PerCompilerFlavor ghcOpts _ = options biBuildInfo
     extOpts = map (("-X" ++) . D.display) (usedExtensions biBuildInfo)
     srcOpts =
         map (("-i" <>) . toFilePathNoTrailingSep)
@@ -528,7 +531,7 @@
   -> Map PackageName VersionRange
 packageDependencies pkgConfig pkg' =
   M.fromListWith intersectVersionRanges $
-  map (depName &&& depRange) $
+  map (depPkgName &&& depVerRange) $
   concatMap targetBuildDepends (allBuildInfo' pkg) ++
   maybe [] setupDepends (setupBuildInfo pkg)
   where
@@ -680,7 +683,7 @@
     return (modules, files, dfiles, warnings)
   where
     libComponent = const CLib
-    internalLibComponent = CInternalLib . T.pack . maybe "" Cabal.unUnqualComponentName . libName
+    internalLibComponent = CInternalLib . T.pack . maybe "" Cabal.unUnqualComponentName . libraryNameString . libName
     exeComponent = CExe . T.pack . Cabal.unUnqualComponentName . exeName
     testComponent = CTest . T.pack . Cabal.unUnqualComponentName . testName
     benchComponent = CBench . T.pack . Cabal.unUnqualComponentName . benchmarkName
@@ -859,7 +862,7 @@
           desc {library =
                   fmap (resolveConditions rc updateLibDeps) mlib
                ,subLibraries =
-                  map (\(n, v) -> (resolveConditions rc updateLibDeps v){libName=Just n})
+                  map (\(n, v) -> (resolveConditions rc updateLibDeps v){libName=LSubLibName n})
                       subLibs
                ,foreignLibs =
                   map (\(n, v) -> (resolveConditions rc updateForeignLibDeps v){foreignLibName=n})
@@ -981,18 +984,7 @@
                     Impl flavor range ->
                       case (flavor, rcCompilerVersion rc) of
                         (GHC, ACGhc vghc) -> vghc `withinRange` range
-                        (GHC, ACGhcjs _ vghc) -> vghc `withinRange` range
-                        (GHCJS, ACGhcjs vghcjs _) ->
-                          vghcjs `withinRange` range
                         _ -> False
-
--- | Get the name of a dependency.
-depName :: Dependency -> PackageName
-depName (Dependency n _) = n
-
--- | Get the version range of a dependency.
-depRange :: Dependency -> VersionRange
-depRange (Dependency _ r) = r
 
 -- | Try to resolve the list of base names in the given directory by
 -- looking for unique instances of base names applied with the given
diff --git a/src/Stack/Path.hs b/src/Stack/Path.hs
--- a/src/Stack/Path.hs
+++ b/src/Stack/Path.hs
@@ -13,9 +13,7 @@
 import           Data.List (intercalate)
 import qualified Data.Text as T
 import qualified Data.Text.IO as T
-import           Lens.Micro (lens)
 import qualified Options.Applicative as OA
-import           Pantry (HasPantryConfig (..))
 import           Path
 import           Path.Extra
 import           Stack.Constants
diff --git a/src/Stack/Prelude.hs b/src/Stack/Prelude.hs
--- a/src/Stack/Prelude.hs
+++ b/src/Stack/Prelude.hs
@@ -41,8 +41,6 @@
 import qualified Data.Conduit.List as CL
 import           Data.Conduit.Process.Typed (withLoggedProcess_, createSource, byteStringInput)
 import           RIO.Process (HasProcessContext (..), ProcessContext, setStdin, closed, getStderr, getStdout, proc, withProcessWait_, setStdout, setStderr, ProcessConfig, readProcess_, workingDirL, waitExitCode)
-import           Data.Text.Encoding (decodeUtf8With)
-import           Data.Text.Encoding.Error (lenientDecode)
 
 import qualified Data.Text.IO as T
 import qualified RIO.Text as T
@@ -216,4 +214,4 @@
 writeBinaryFileAtomic :: MonadIO m => Path absrel File -> Builder -> m ()
 writeBinaryFileAtomic fp builder =
     liftIO $
-    withBinaryFileAtomic (toFilePath fp) WriteMode (\h -> hPutBuilder h builder)
+    withBinaryFileAtomic (toFilePath fp) WriteMode (`hPutBuilder` builder)
diff --git a/src/Stack/Runners.hs b/src/Stack/Runners.hs
--- a/src/Stack/Runners.hs
+++ b/src/Stack/Runners.hs
@@ -33,9 +33,9 @@
 import           Stack.Types.Config
 import           Stack.Types.Docker (dockerEnable)
 import           Stack.Types.Nix (nixEnable)
-import           Stack.Types.Version (stackMinorVersion, stackVersion, minorVersion)
+import           Stack.Types.Version (stackMinorVersion, minorVersion)
 import           System.Console.ANSI (hSupportsANSIWithoutEmulation)
-import           System.Console.Terminal.Size (size, width)
+import           System.Terminal (getTerminalWidth)
 
 -- | Ensure that no project settings are used when running 'withConfig'.
 withGlobalProject :: RIO Runner a -> RIO Runner a
@@ -137,16 +137,15 @@
 withRunnerGlobal :: GlobalOpts -> RIO Runner a -> IO a
 withRunnerGlobal go inner = do
   colorWhen <-
-    case getFirst $ configMonoidColorWhen $ globalConfigMonoid go of
-      Nothing -> defaultColorWhen
-      Just colorWhen -> pure colorWhen
+    maybe defaultColorWhen pure $
+    getFirst $ configMonoidColorWhen $ globalConfigMonoid go
   useColor <- case colorWhen of
     ColorNever -> return False
     ColorAlways -> return True
     ColorAuto -> fromMaybe True <$>
                           hSupportsANSIWithoutEmulation stderr
   termWidth <- clipWidth <$> maybe (fromMaybe defaultTerminalWidth
-                                    <$> fmap (fmap width) size)
+                                    <$> getTerminalWidth)
                                    pure (globalTermWidth go)
   menv <- mkDefaultProcessContext
   logOptions0 <- logOptionsHandle stderr False
diff --git a/src/Stack/SDist.hs b/src/Stack/SDist.hs
--- a/src/Stack/SDist.hs
+++ b/src/Stack/SDist.hs
@@ -19,14 +19,12 @@
 import           Control.Applicative
 import           Control.Concurrent.Execute (ActionContext(..), Concurrency(..))
 import           Stack.Prelude hiding (Display (..))
-import           Control.Monad.Reader.Class (local)
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Char8 as S8
 import qualified Data.ByteString.Lazy as L
 import           Data.Char (toLower)
 import           Data.Data (cast)
 import           Data.List
-import           Data.List.NonEmpty (NonEmpty)
 import qualified Data.List.NonEmpty as NE
 import qualified Data.Map.Strict as Map
 import qualified Data.Set as Set
@@ -43,7 +41,6 @@
 import           Distribution.PackageDescription.PrettyPrint (showGenericPackageDescription)
 import qualified Distribution.Types.UnqualComponentName as Cabal
 import           Distribution.Version (simplifyVersionRange, orLaterVersion, earlierVersion, hasUpperBound, hasLowerBound)
-import           Lens.Micro (set)
 import           Path
 import           Path.IO hiding (getModificationTime, getPermissions, withSystemTempDir)
 import           RIO.PrettyPrint
@@ -244,15 +241,16 @@
       )
   where
     addBounds :: Set PackageName -> InstallMap -> InstalledMap -> Dependency -> Dependency
-    addBounds internalPackages installMap installedMap dep@(Dependency name range) =
+    -- FIXME
+    addBounds internalPackages installMap installedMap dep@(Dependency name range _) =
       if name `Set.member` internalPackages
         then dep
         else case foundVersion of
           Nothing -> dep
-          Just version -> Dependency name $ simplifyVersionRange
+          Just version -> Dependency name (simplifyVersionRange
             $ (if toAddUpper && not (hasUpperBound range) then addUpper version else id)
             $ (if toAddLower && not (hasLowerBound range) then addLower version else id)
-              range
+              range) Set.empty
       where
         foundVersion =
           case Map.lookup name installMap of
diff --git a/src/Stack/Script.hs b/src/Stack/Script.hs
--- a/src/Stack/Script.hs
+++ b/src/Stack/Script.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -21,7 +22,11 @@
 import           Distribution.Types.VersionRange (withinRange)
 import           Distribution.System        (Platform (..))
 import qualified Pantry.SHA256 as SHA256
+#if MIN_VERSION_path(0,7,0)
+import           Path hiding (replaceExtension)
+#else
 import           Path
+#endif
 import           Path.IO
 import qualified Stack.Build
 import           Stack.Build.Installed
@@ -256,8 +261,6 @@
           pure $ compiler == GHC && version `withinRange` range
         ACGhcGit {} ->
           pure $ compiler == GHC
-        ACGhcjs version _ghcVersion ->
-          pure $ compiler == GHCJS && version `withinRange` range
       -- currently we don't do flag checking here
       checkCond other = Left other
       mlibrary = snd . C.simplifyCondTree checkCond <$> PD.condLibrary gpd
diff --git a/src/Stack/Setup.hs b/src/Stack/Setup.hs
--- a/src/Stack/Setup.hs
+++ b/src/Stack/Setup.hs
@@ -31,14 +31,12 @@
 import qualified    Codec.Archive.Tar as Tar
 import              Conduit
 import              Control.Applicative (empty)
-import              Control.Monad.State (get, put, modify)
 import "cryptonite" Crypto.Hash (SHA1(..), SHA256(..))
 import              Pantry.Internal.AesonExtended
 import qualified    Data.ByteString as S
 import qualified    Data.ByteString.Lazy as LBS
 import qualified    Data.Conduit.Binary as CB
 import              Data.Conduit.Lazy (lazyConsume)
-import              Data.Conduit.Lift (evalStateC)
 import qualified    Data.Conduit.List as CL
 import              Data.Conduit.Process.Typed (createSource)
 import              Data.Conduit.Zlib          (ungzip)
@@ -50,23 +48,21 @@
 import qualified    Data.Text as T
 import qualified    Data.Text.Encoding as T
 import qualified    Data.Text.Encoding.Error as T
-import              Data.Time.Clock (NominalDiffTime, diffUTCTime, getCurrentTime)
 import qualified    Data.Yaml as Yaml
 import              Distribution.System (OS, Arch (..), Platform (..))
 import qualified    Distribution.System as Cabal
 import              Distribution.Text (simpleParse)
 import              Distribution.Types.PackageName (mkPackageName)
 import              Distribution.Version (mkVersion)
-import              Lens.Micro (set)
-import              Network.HTTP.StackClient (CheckHexDigest (..), DownloadRequest (..), HashCheck (..),
-                                              drRetryPolicyDefault, getResponseBody, getResponseStatusCode,
-                                              httpLbs, httpJSON, parseRequest, parseUrlThrow, setGithubHeaders,
-                                              verifiedDownload, withResponse)
-import              Path
+import              Network.HTTP.StackClient (CheckHexDigest (..), HashCheck (..),
+                                              getResponseBody, getResponseStatusCode, httpLbs, httpJSON,
+                                              mkDownloadRequest, parseRequest, parseUrlThrow, setGithubHeaders,
+                                              setHashChecks, setLengthCheck, verifiedDownloadWithProgress, withResponse)
+import              Path hiding (fileExtension)
 import              Path.CheckInstall (warnInstallSearchPathIssues)
+import              Path.Extended (fileExtension)
 import              Path.Extra (toFilePathNoTrailingSep)
 import              Path.IO hiding (findExecutable, withSystemTempDir)
-import              Prelude (until)
 import qualified    Pantry
 import qualified    RIO
 import              RIO.List
@@ -95,7 +91,6 @@
 import              System.FilePath (searchPathSeparator)
 import qualified    System.FilePath as FP
 import              System.Permissions (setFileExecutable)
-import              Text.Printf (printf)
 import              System.Uname (getRelease)
 import              Data.List.Split (splitOn)
 
@@ -121,12 +116,8 @@
     -- ^ Do not use a custom msys installation on Windows
     , soptsResolveMissingGHC :: !(Maybe Text)
     -- ^ Message shown to user for how to resolve the missing GHC
-    , soptsSetupInfoYaml :: !FilePath
-    -- ^ Location of the main stack-setup.yaml file
     , soptsGHCBindistURL :: !(Maybe String)
     -- ^ Alternate GHC binary distribution (requires custom GHCVariant)
-    , soptsGHCJSBootOpts :: [String]
-    -- ^ Additional ghcjs-boot options, the default is "--clean"
     }
     deriving Show
 data SetupException = UnsupportedSetupCombo OS Arch
@@ -138,12 +129,9 @@
                     | RequireCustomGHCVariant
                     | ProblemWhileDecompressing (Path Abs File)
                     | SetupInfoMissingSevenz
-                    | GHCJSRequiresStandardVariant
-                    | GHCJSNotBooted
                     | DockerStackExeNotFound Version Text
                     | UnsupportedSetupConfiguration
                     | InvalidGhcAt (Path Abs File) SomeException
-                    | NoLongerBuildGhcjs
     deriving Typeable
 instance Exception SetupException
 instance Show SetupException where
@@ -182,10 +170,6 @@
         "Problem while decompressing " ++ toFilePath archive
     show SetupInfoMissingSevenz =
         "SetupInfo missing Sevenz EXE/DLL"
-    show GHCJSRequiresStandardVariant =
-        "stack does not yet support using --ghc-variant with GHCJS"
-    show GHCJSNotBooted =
-        "GHCJS does not yet have its boot packages installed.  Use \"stack setup\" to attempt to run ghcjs-boot."
     show (DockerStackExeNotFound stackVersion' osKey) = concat
         [ stackProgName
         , "-"
@@ -199,8 +183,6 @@
         "I don't know how to install GHC on your system configuration, please install manually"
     show (InvalidGhcAt compiler e) =
         "Found an invalid compiler at " ++ show (toFilePath compiler) ++ ": " ++ displayException e
-    show NoLongerBuildGhcjs =
-        "Since Stack 2.0, Stack does not support building GHCJS itself"
 
 -- | Modify the environment variables (like PATH) appropriately, possibly doing installation too
 setupEnv :: NeedTargets
@@ -213,7 +195,9 @@
     let stackYaml = bcStackYaml bc
     platform <- view platformL
     wcVersion <- view wantedCompilerVersionL
-    wc <- view $ wantedCompilerVersionL.to wantedToActual.whichCompilerL
+    wanted <- view wantedCompilerVersionL
+    actual <- either throwIO pure $ wantedToActual wanted
+    let wc = actual^.whichCompilerL
     let sopts = SetupOpts
             { soptsInstallIfMissing = configInstallGHC config
             , soptsUseSystem = configSystemGHC config
@@ -225,9 +209,7 @@
             , soptsSkipGhcCheck = configSkipGHCCheck config
             , soptsSkipMsys = configSkipMsys config
             , soptsResolveMissingGHC = mResolveMissingGHC
-            , soptsSetupInfoYaml = defaultSetupInfoYaml
             , soptsGHCBindistURL = Nothing
-            , soptsGHCJSBootOpts = ["--clean"]
             }
 
     (compilerPaths, ghcBin) <- ensureCompilerAndMsys sopts
@@ -450,13 +432,14 @@
 -- | Ensure both the compiler and the msys toolchain are installed and
 -- provide the PATHs to add if necessary
 ensureCompilerAndMsys
-  :: (HasConfig env, HasGHCVariant env)
+  :: (HasBuildConfig env, HasGHCVariant env)
   => SetupOpts
   -> RIO env (CompilerPaths, ExtraDirs)
 ensureCompilerAndMsys sopts = do
-  didWarn <- warnUnsupportedCompiler $ getGhcVersion $ wantedToActual $ soptsWantedCompiler sopts
+  actual <- either throwIO pure $ wantedToActual $ soptsWantedCompiler sopts
+  didWarn <- warnUnsupportedCompiler $ getGhcVersion actual
 
-  getSetupInfo' <- memoizeRef (getSetupInfo (soptsSetupInfoYaml sopts))
+  getSetupInfo' <- memoizeRef getSetupInfo
   (cp, ghcPaths) <- ensureCompiler sopts getSetupInfo'
 
   warnUnsupportedCompilerCabal cp didWarn
@@ -482,9 +465,9 @@
         logWarn "For more information, see: https://github.com/commercialhaskell/stack/issues/648"
         logWarn ""
         pure True
-    | ghcVersion >= mkVersion [8, 7] -> do
+    | ghcVersion >= mkVersion [8, 11] -> do
         logWarn $
-          "Stack has not been tested with GHC versions above 8.6, and using " <>
+          "Stack has not been tested with GHC versions above 8.10, and using " <>
           fromString (versionString ghcVersion) <>
           ", this may fail"
         pure True
@@ -509,9 +492,9 @@
         logWarn "This invocation will most likely fail."
         logWarn "To fix this, either use an older version of Stack or a newer resolver"
         logWarn "Acceptable resolvers: lts-3.0/nightly-2015-05-05 or later"
-    | cabalVersion >= mkVersion [2, 5] ->
+    | cabalVersion >= mkVersion [3, 3] ->
         logWarn $
-          "Stack has not been tested with Cabal versions above 2.4, but version " <>
+          "Stack has not been tested with Cabal versions above 3.2, but version " <>
           fromString (versionString cabalVersion) <>
           " was found, this may fail"
     | otherwise -> pure ()
@@ -519,7 +502,7 @@
 -- | Ensure that the msys toolchain is installed if necessary and
 -- provide the PATHs to add if necessary
 ensureMsys
-  :: HasConfig env
+  :: HasBuildConfig env
   => SetupOpts
   -> Memoized SetupInfo
   -> RIO env (Maybe Tool)
@@ -549,7 +532,7 @@
       _ -> return Nothing
 
 installGhcBindist
-  :: HasConfig env
+  :: HasBuildConfig env
   => SetupOpts
   -> Memoized SetupInfo
   -> [Tool]
@@ -560,14 +543,14 @@
         isWanted = isWantedCompiler (soptsCompilerCheck sopts) (soptsWantedCompiler sopts)
     config <- view configL
     ghcVariant <- view ghcVariantL
+    wc <- either throwIO (pure . whichCompiler) $ wantedToActual wanted
     possibleCompilers <-
-            case whichCompiler $ wantedToActual wanted of
+            case wc of
                 Ghc -> do
                     ghcBuilds <- getGhcBuilds
                     forM ghcBuilds $ \ghcBuild -> do
                         ghcPkgName <- parsePackageNameThrowing ("ghc" ++ ghcVariantSuffix ghcVariant ++ compilerBuildSuffix ghcBuild)
                         return (getInstalledTool installed ghcPkgName (isWanted . ACGhc), ghcBuild)
-                Ghcjs -> return []
     let existingCompilers = concatMap
             (\(installedCompiler, compilerBuild) ->
                 case (installedCompiler, soptsForceReinstall sopts) of
@@ -608,15 +591,15 @@
                     (soptsStackYaml sopts)
                     suggestion
 
--- | Ensure compiler (ghc or ghcjs) is installed, without worrying about msys
+-- | Ensure compiler is installed, without worrying about msys
 ensureCompiler
-  :: forall env. (HasConfig env, HasGHCVariant env)
+  :: forall env. (HasBuildConfig env, HasGHCVariant env)
   => SetupOpts
   -> Memoized SetupInfo
   -> RIO env (CompilerPaths, ExtraDirs)
 ensureCompiler sopts getSetupInfo' = do
     let wanted = soptsWantedCompiler sopts
-        wc = whichCompiler $ wantedToActual wanted
+    wc <- either throwIO (pure . whichCompiler) $ wantedToActual wanted
 
     Platform expectedArch _ <- view platformL
 
@@ -652,7 +635,7 @@
         pure (cp, paths)
 
 ensureSandboxedCompiler
-  :: HasConfig env
+  :: HasBuildConfig env
   => SetupOpts
   -> Memoized SetupInfo
   -> RIO env (CompilerPaths, ExtraDirs)
@@ -670,18 +653,18 @@
        _ -> installGhcBindist sopts getSetupInfo' installed
     paths <- extraDirs compilerTool
 
-    let wc = whichCompiler $ wantedToActual wanted
+    wc <- either throwIO (pure . whichCompiler) $ wantedToActual wanted
     menv0 <- view processContextL
     m <- either throwM return
        $ augmentPathMap (toFilePath <$> edBins paths) (view envVarsL menv0)
     menv <- mkProcessContext (removeHaskellEnvVars m)
 
-    let names =
-          case wanted of
-            WCGhc version -> ["ghc-" ++ versionString version, "ghc"]
-            WCGhcGit{} -> ["ghc"]
-            WCGhcjs{} -> ["ghcjs"]
-        loop [] = do
+    names <-
+      case wanted of
+        WCGhc version -> pure ["ghc-" ++ versionString version, "ghc"]
+        WCGhcGit{} -> pure ["ghc"]
+        WCGhcjs{} -> throwIO GhcjsNotSupported
+    let loop [] = do
           logError $ "Looked for sandboxed compiler named one of: " <> displayShow names
           logError $ "Could not find it on the paths " <> displayShow (edBins paths)
           throwString "Could not find sandboxed compiler"
@@ -712,7 +695,6 @@
           let prefix =
                 case wc of
                   Ghc -> "ghc-"
-                  Ghcjs -> "ghcjs-"
           fmap ("-" ++) $ stripPrefix prefix $ toFilePath $ filename compiler
         suffixes = maybe id (:) msuffixWithVersion [suffixNoVersion]
         findHelper :: (WhichCompiler -> [String]) -> RIO env (Path Abs File)
@@ -729,7 +711,6 @@
           loop toTry
     pkg <- fmap GhcPkgExe $ findHelper $ \case
                                Ghc -> ["ghc-pkg"]
-                               Ghcjs -> ["ghcjs-pkg"]
 
     menv0 <- view processContextL
     menv <- mkProcessContext (removeHaskellEnvVars (view envVarsL menv0))
@@ -737,11 +718,9 @@
     interpreter <- findHelper $
                    \case
                       Ghc -> ["runghc"]
-                      Ghcjs -> ["runghcjs"]
     haddock <- findHelper $
                \case
                   Ghc -> ["haddock", "haddock-ghc"]
-                  Ghcjs -> ["haddock-ghcjs"]
     infobs <- proc (toFilePath compiler) ["--info"]
             $ fmap (toStrictBytes . fst) . readProcess_
     infotext <-
@@ -774,7 +753,6 @@
               logWarn "Key 'Project version' not found in GHC info"
               getCompilerVersion wc compiler
             Just versionString' -> ACGhc <$> parseVersionThrowing versionString'
-        Ghcjs -> getCompilerVersion wc compiler
     globaldb <-
       case eglobaldb of
         Left e -> do
@@ -826,7 +804,7 @@
 buildGhcFromSource :: forall env.
    ( HasTerm env
    , HasProcessContext env
-   , HasConfig env
+   , HasBuildConfig env
    ) => Memoized SetupInfo -> [Tool] -> CompilerRepository -> Text -> Text
    -> RIO env (Tool, CompilerBuild)
 buildGhcFromSource getSetupInfo' installed (CompilerRepository url) commitId flavour = do
@@ -875,9 +853,13 @@
          bindistPath <- parseRelDir "_build/bindist"
          (_,files) <- listDir (cwd </> bindistPath)
          let
-           isBindist p = "ghc-" `isPrefixOf` (toFilePath (filename p))
-                         && fileExtension (filename p) == ".xz"
-           mbindist = filter isBindist files
+           isBindist p = do
+             extension <- fileExtension (filename p)
+
+             return $ "ghc-" `isPrefixOf` (toFilePath (filename p))
+                         && extension == ".xz"
+
+         mbindist <- filterM isBindist files
          case mbindist of
            [bindist] -> do
                let bindist' = T.pack (toFilePath bindist)
@@ -1052,44 +1034,43 @@
   -> ConduitT i (Path Abs File) (RIO env) ()
 sourceSystemCompilers wanted = do
   searchPath <- view exeSearchPathL
+  names <-
+    case wanted of
+      WCGhc version -> pure
+        [ "ghc-" ++ versionString version
+        , "ghc"
+        ]
+      WCGhcjs{} -> throwIO GhcjsNotSupported
+      WCGhcGit{} -> pure [] -- only use sandboxed versions
   for_ names $ \name -> for_ searchPath $ \dir -> do
     fp <- resolveFile' $ addExe $ dir FP.</> name
     exists <- doesFileExist fp
     when exists $ yield fp
   where
-    names =
-      case wanted of
-        WCGhc version ->
-          [ "ghc-" ++ versionString version
-          , "ghc"
-          ]
-        WCGhcjs{} -> ["ghcjs"]
-        WCGhcGit{} -> [] -- only use sandboxed versions
     addExe
       | osIsWindows = (++ ".exe")
       | otherwise = id
 
 -- | Download the most recent SetupInfo
-getSetupInfo :: HasConfig env => String -> RIO env SetupInfo
-getSetupInfo stackSetupYaml = do
+getSetupInfo :: HasConfig env => RIO env SetupInfo
+getSetupInfo = do
     config <- view configL
-    setupInfos <-
-        mapM
-            loadSetupInfo
-            (SetupInfoFileOrURL stackSetupYaml :
-             configSetupInfoLocations config)
-    return (mconcat setupInfos)
+    let inlineSetupInfo = configSetupInfoInline config
+        locations' = configSetupInfoLocations config
+        locations = if null locations' then [defaultSetupInfoYaml] else locations'
+
+    resolvedSetupInfos <- mapM loadSetupInfo locations
+    return (inlineSetupInfo <> mconcat resolvedSetupInfos)
   where
-    loadSetupInfo (SetupInfoInline si) = return si
-    loadSetupInfo (SetupInfoFileOrURL urlOrFile) = do
-        bs <-
-            case parseUrlThrow urlOrFile of
-                Just req -> liftM (LBS.toStrict . getResponseBody) $ httpLbs req
-                Nothing -> liftIO $ S.readFile urlOrFile
-        WithJSONWarnings si warnings <- either throwM return (Yaml.decodeEither' bs)
-        when (urlOrFile /= defaultSetupInfoYaml) $
-            logJSONWarnings urlOrFile warnings
-        return si
+    loadSetupInfo urlOrFile = do
+      bs <-
+          case parseUrlThrow urlOrFile of
+              Just req -> liftM (LBS.toStrict . getResponseBody) $ httpLbs req
+              Nothing -> liftIO $ S.readFile urlOrFile
+      WithJSONWarnings si warnings <- either throwM return (Yaml.decodeEither' bs)
+      when (urlOrFile /= defaultSetupInfoYaml) $
+          logJSONWarnings urlOrFile warnings
+      return si
 
 getInstalledTool :: [Tool]            -- ^ already installed
                  -> PackageName       -- ^ package to find
@@ -1108,7 +1089,7 @@
             else Nothing
     goodPackage _ = Nothing
 
-downloadAndInstallTool :: HasTerm env
+downloadAndInstallTool :: (HasTerm env, HasBuildConfig env)
                        => Path Abs Dir
                        -> DownloadInfo
                        -> Tool
@@ -1127,7 +1108,7 @@
     liftIO $ ignoringAbsence (removeDirRecur tempDir)
     return tool
 
-downloadAndInstallCompiler :: (HasConfig env, HasGHCVariant env)
+downloadAndInstallCompiler :: (HasBuildConfig env, HasGHCVariant env)
                            => CompilerBuild
                            -> SetupInfo
                            -> WantedCompiler
@@ -1175,7 +1156,7 @@
     let tool = Tool $ PackageIdentifier ghcPkgName selectedVersion
     downloadAndInstallTool (configLocalPrograms config) (gdiDownloadInfo downloadInfo) tool (installer si)
 
-downloadAndInstallCompiler _ _ WCGhcjs{} _ _ = throwIO NoLongerBuildGhcjs
+downloadAndInstallCompiler _ _ WCGhcjs{} _ _ = throwIO GhcjsNotSupported
 
 downloadAndInstallCompiler _ _ WCGhcGit{} _ _ =
     error "downloadAndInstallCompiler: shouldn't be reached with ghc-git"
@@ -1199,7 +1180,7 @@
 
 -- | Download and install the first available compiler build.
 downloadAndInstallPossibleCompilers
-    :: (HasGHCVariant env, HasConfig env)
+    :: (HasGHCVariant env, HasBuildConfig env)
     => [CompilerBuild]
     -> SetupInfo
     -> WantedCompiler
@@ -1266,41 +1247,53 @@
         Platform AArch64               Cabal.Linux   -> return "linux-aarch64"
         Platform arch os -> throwM $ UnsupportedSetupCombo os arch
 
+downloadOrUseLocal
+    :: (HasTerm env, HasBuildConfig env)
+    => Text -> DownloadInfo -> Path Abs File -> RIO env (Path Abs File)
+downloadOrUseLocal downloadLabel downloadInfo destination =
+  case url of
+    (parseUrlThrow -> Just _) -> do
+        ensureDir (parent destination)
+        chattyDownload downloadLabel downloadInfo destination
+        return destination
+    (parseAbsFile -> Just path) -> do
+        warnOnIgnoredChecks
+        return path
+    (parseRelFile -> Just path) -> do
+        warnOnIgnoredChecks
+        root <- view projectRootL
+        return (root </> path)
+    _ ->
+        throwString $ "Error: `url` must be either an HTTP URL or a file path: " ++ url
+  where
+    url = T.unpack $ downloadInfoUrl downloadInfo
+    warnOnIgnoredChecks = do
+      let DownloadInfo{downloadInfoContentLength=contentLength, downloadInfoSha1=sha1,
+                       downloadInfoSha256=sha256} = downloadInfo
+      when (isJust contentLength) $
+        logWarn "`content-length` is not checked and should not be specified when `url` is a file path"
+      when (isJust sha1) $
+        logWarn "`sha1` is not checked and should not be specified when `url` is a file path"
+      when (isJust sha256) $
+        logWarn "`sha256` is not checked and should not be specified when `url` is a file path"
+
 downloadFromInfo
-    :: HasTerm env
+    :: (HasTerm env, HasBuildConfig env)
     => Path Abs Dir -> DownloadInfo -> Tool -> RIO env (Path Abs File, ArchiveType)
 downloadFromInfo programsDir downloadInfo tool = do
-    at <-
+    archiveType <-
         case extension of
             ".tar.xz" -> return TarXz
             ".tar.bz2" -> return TarBz2
             ".tar.gz" -> return TarGz
             ".7z.exe" -> return SevenZ
             _ -> throwString $ "Error: Unknown extension for url: " ++ url
+
     relativeFile <- parseRelFile $ toolString tool ++ extension
-    path <- case url of
-        (parseUrlThrow -> Just _) -> do
-            let path = programsDir </> relativeFile
-            ensureDir programsDir
-            chattyDownload (T.pack (toolString tool)) downloadInfo path
-            return path
-        (parseAbsFile -> Just path) -> do
-            let DownloadInfo{downloadInfoContentLength=contentLength, downloadInfoSha1=sha1,
-                             downloadInfoSha256=sha256} =
-                    downloadInfo
-            when (isJust contentLength) $
-                logWarn ("`content-length` in not checked \n" <>
-                          "and should not be specified when `url` is a file path")
-            when (isJust sha1) $
-                logWarn ("`sha1` is not checked and \n" <>
-                          "should not be specified when `url` is a file path")
-            when (isJust sha256) $
-                logWarn ("`sha256` is not checked and \n" <>
-                          "should not be specified when `url` is a file path")
-            return path
-        _ ->
-            throwString $ "Error: `url` must be either an HTTP URL or absolute file path: " ++ url
-    return (path, at)
+    let destinationPath = programsDir </> relativeFile
+    localPath <- downloadOrUseLocal (T.pack (toolString tool)) downloadInfo destinationPath
+    return (localPath, archiveType)
+
   where
     url = T.unpack $ downloadInfoUrl downloadInfo
     extension = loop url
@@ -1311,6 +1304,7 @@
           where
             (fp', ext) = FP.splitExtension fp
 
+
 data ArchiveType
     = TarBz2
     | TarXz
@@ -1438,7 +1432,7 @@
             Left _ -> y
             Right x' -> return $ Right x'
 
-installGHCWindows :: HasConfig env
+installGHCWindows :: HasBuildConfig env
                   => Maybe Version
                   -> SetupInfo
                   -> Path Abs File
@@ -1451,7 +1445,7 @@
     withUnpackedTarball7z "GHC" si archiveFile archiveType tarComponent destDir
     logInfo $ "GHC installed to " <> fromString (toFilePath destDir)
 
-installMsys2Windows :: HasConfig env
+installMsys2Windows :: HasBuildConfig env
                   => Text -- ^ OS Key
                   -> SetupInfo
                   -> Path Abs File
@@ -1492,7 +1486,7 @@
 
 -- | Unpack a compressed tarball using 7zip.  Expects a single directory in
 -- the unpacked results, which is renamed to the destination directory.
-withUnpackedTarball7z :: HasConfig env
+withUnpackedTarball7z :: HasBuildConfig env
                       => String -- ^ Name of tool, used in error messages
                       -> SetupInfo
                       -> Path Abs File -- ^ Path to archive file
@@ -1533,20 +1527,20 @@
 -- | Download 7z as necessary, and get a function for unpacking things.
 --
 -- Returned function takes an unpack directory and archive.
-setup7z :: (HasConfig env, MonadIO m)
+setup7z :: (HasBuildConfig env, MonadIO m)
         => SetupInfo
         -> RIO env (Path Abs Dir -> Path Abs File -> m ())
 setup7z si = do
     dir <- view $ configL.to configLocalPrograms
     ensureDir dir
-    let exe = dir </> relFile7zexe
-        dll = dir </> relFile7zdll
+    let exeDestination = dir </> relFile7zexe
+        dllDestination = dir </> relFile7zdll
     case (siSevenzDll si, siSevenzExe si) of
         (Just sevenzDll, Just sevenzExe) -> do
-            chattyDownload "7z.dll" sevenzDll dll
-            chattyDownload "7z.exe" sevenzExe exe
+            _ <- downloadOrUseLocal "7z.dll" sevenzDll dllDestination
+            exePath <- downloadOrUseLocal "7z.exe" sevenzExe exeDestination
             withRunInIO $ \run -> return $ \outdir archive -> liftIO $ run $ do
-                let cmd = toFilePath exe
+                let cmd = toFilePath exePath
                     args =
                         [ "x"
                         , "-o" ++ toFilePath outdir
@@ -1618,92 +1612,16 @@
     when (null hashChecks) $ logWarn $
         "No sha1 or sha256 found in metadata," <>
         " download hash won't be checked."
-    let dReq = DownloadRequest
-            { drRequest = req
-            , drHashChecks = hashChecks
-            , drLengthCheck = mtotalSize
-            , drRetryPolicy = drRetryPolicyDefault
-            }
-    x <- verifiedDownload dReq path chattyDownloadProgress
+    let dReq = setHashChecks hashChecks $
+               setLengthCheck mtotalSize $
+               mkDownloadRequest req
+    x <- verifiedDownloadWithProgress dReq path label mtotalSize
     if x
         then logStickyDone ("Downloaded " <> RIO.display label <> ".")
         else logStickyDone "Already downloaded."
   where
     mtotalSize = downloadInfoContentLength downloadInfo
-    chattyDownloadProgress _ = do
-        _ <- logSticky $ RIO.display label <> ": download has begun"
-        CL.map (Sum . S.length)
-          .| chunksOverTime 1
-          .| go
-      where
-        go = evalStateC 0 $ awaitForever $ \(Sum size) -> do
-            modify (+ size)
-            totalSoFar <- get
-            logSticky $ fromString $
-                case mtotalSize of
-                    Nothing -> chattyProgressNoTotal totalSoFar
-                    Just 0 -> chattyProgressNoTotal totalSoFar
-                    Just totalSize -> chattyProgressWithTotal totalSoFar totalSize
 
-        -- Example: ghc: 42.13 KiB downloaded...
-        chattyProgressNoTotal totalSoFar =
-            printf ("%s: " <> bytesfmt "%7.2f" totalSoFar <> " downloaded...")
-                   (T.unpack label)
-
-        -- Example: ghc: 50.00 MiB / 100.00 MiB (50.00%) downloaded...
-        chattyProgressWithTotal totalSoFar total =
-          printf ("%s: " <>
-                  bytesfmt "%7.2f" totalSoFar <> " / " <>
-                  bytesfmt "%.2f" total <>
-                  " (%6.2f%%) downloaded...")
-                 (T.unpack label)
-                 percentage
-          where percentage :: Double
-                percentage = fromIntegral totalSoFar / fromIntegral total * 100
-
--- | Given a printf format string for the decimal part and a number of
--- bytes, formats the bytes using an appropiate unit and returns the
--- formatted string.
---
--- >>> bytesfmt "%.2" 512368
--- "500.359375 KiB"
-bytesfmt :: Integral a => String -> a -> String
-bytesfmt formatter bs = printf (formatter <> " %s")
-                               (fromIntegral (signum bs) * dec :: Double)
-                               (bytesSuffixes !! i)
-  where
-    (dec,i) = getSuffix (abs bs)
-    getSuffix n = until p (\(x,y) -> (x / 1024, y+1)) (fromIntegral n,0)
-      where p (n',numDivs) = n' < 1024 || numDivs == (length bytesSuffixes - 1)
-    bytesSuffixes :: [String]
-    bytesSuffixes = ["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]
-
--- Await eagerly (collect with monoidal append),
--- but space out yields by at least the given amount of time.
--- The final yield may come sooner, and may be a superfluous mempty.
--- Note that Integer and Float literals can be turned into NominalDiffTime
--- (these literals are interpreted as "seconds")
-chunksOverTime :: (Monoid a, Semigroup a, MonadIO m) => NominalDiffTime -> ConduitM a a m ()
-chunksOverTime diff = do
-    currentTime <- liftIO getCurrentTime
-    evalStateC (currentTime, mempty) go
-  where
-    -- State is a tuple of:
-    -- * the last time a yield happened (or the beginning of the sink)
-    -- * the accumulated awaits since the last yield
-    go = await >>= \case
-      Nothing -> do
-        (_, acc) <- get
-        yield acc
-      Just a -> do
-        (lastTime, acc) <- get
-        let acc' = acc <> a
-        currentTime <- liftIO getCurrentTime
-        if diff < diffUTCTime currentTime lastTime
-          then put (currentTime, mempty) >> yield acc'
-          else put (lastTime,    acc')
-        go
-
 -- | Perform a basic sanity check of GHC
 sanityCheck :: (HasProcessContext env, HasLogFunc env)
             => Path Abs File -> RIO env ()
@@ -1725,7 +1643,6 @@
 -- Remove potentially confusing environment variables
 removeHaskellEnvVars :: Map Text Text -> Map Text Text
 removeHaskellEnvVars =
-    Map.delete "GHCJS_PACKAGE_PATH" .
     Map.delete "GHC_PACKAGE_PATH" .
     Map.delete "GHC_ENVIRONMENT" .
     Map.delete "HASKELL_PACKAGE_SANDBOX" .
diff --git a/src/Stack/Setup/Installed.hs b/src/Stack/Setup/Installed.hs
--- a/src/Stack/Setup/Installed.hs
+++ b/src/Stack/Setup/Installed.hs
@@ -83,16 +83,6 @@
         x <- T.stripSuffix ".installed" $ T.pack $ toFilePath $ filename fp
         parseToolText x
 
--- | See https://github.com/commercialhaskell/stack/issues/4086.
-warnAboutGHCJS :: HasLogFunc env => RIO env ()
-warnAboutGHCJS =
-    logWarn $ "Building a GHCJS project. " <> fromString ghcjsWarning
-
-ghcjsWarning :: String
-ghcjsWarning = unwords
-     [ "Note that GHCJS support in Stack is EXPERIMENTAL"
-     ]
-
 getCompilerVersion
   :: (HasProcessContext env, HasLogFunc env)
   => WhichCompiler
@@ -107,16 +97,6 @@
             x <- ACGhc <$> parseVersionThrowing (T.unpack $ T.decodeUtf8 ghcVersion)
             logDebug $ "GHC version is: " <> display x
             return x
-        Ghcjs -> do
-            warnAboutGHCJS
-            logDebug "Asking GHCJS for its version"
-            -- Output looks like
-            --
-            -- The Glorious Glasgow Haskell Compilation System for JavaScript, version 0.1.0 (GHC 7.10.2)
-            bs <- fst <$> proc (toFilePath exe) ["--version"] readProcess_
-            let (rest, ghcVersion) = T.unpack . T.decodeUtf8 <$> versionFromEnd (BL.toStrict bs)
-                (_, ghcjsVersion) = T.unpack . T.decodeUtf8 <$> versionFromEnd rest
-            ACGhcjs <$> parseVersionThrowing ghcjsVersion <*> parseVersionThrowing ghcVersion
   where
     versionFromEnd = S8.spanEnd isValid . fst . S8.breakEnd isValid
     isValid c = c == '.' || ('0' <= c && c <= '9')
diff --git a/src/Stack/SetupCmd.hs b/src/Stack/SetupCmd.hs
--- a/src/Stack/SetupCmd.hs
+++ b/src/Stack/SetupCmd.hs
@@ -27,25 +27,11 @@
 data SetupCmdOpts = SetupCmdOpts
     { scoCompilerVersion :: !(Maybe WantedCompiler)
     , scoForceReinstall  :: !Bool
-    , scoSetupInfoYaml   :: !String
     , scoGHCBindistURL   :: !(Maybe String)
     , scoGHCJSBootOpts   :: ![String]
     , scoGHCJSBootClean  :: !Bool
     }
 
-setupYamlCompatParser :: OA.Parser String
-setupYamlCompatParser = stackSetupYaml <|> setupInfoYaml
-    where stackSetupYaml = OA.strOption (
-               OA.long "stack-setup-yaml"
-            <> OA.help "DEPRECATED: Use 'setup-info-yaml' instead"
-            <> OA.metavar "URL"
-            <> OA.hidden )
-          setupInfoYaml  = OA.strOption (
-               OA.long "setup-info-yaml"
-            <> OA.help "Alternate URL or absolute path for stack dependencies"
-            <> OA.metavar "URL"
-            <> OA.value defaultSetupInfoYaml )
-
 setupParser :: OA.Parser SetupCmdOpts
 setupParser = SetupCmdOpts
     <$> OA.optional (OA.argument readVersion
@@ -56,7 +42,6 @@
             "reinstall"
             "reinstalling GHC, even if available (incompatible with --system-ghc)"
             OA.idm
-    <*> setupYamlCompatParser
     <*> OA.optional (OA.strOption
             (OA.long "ghc-bindist"
            <> OA.metavar "URL"
@@ -80,7 +65,7 @@
             Right x -> return x
 
 setup
-    :: (HasConfig env, HasGHCVariant env)
+    :: (HasBuildConfig env, HasGHCVariant env)
     => SetupCmdOpts
     -> WantedCompiler
     -> VersionCheck
@@ -99,9 +84,7 @@
         , soptsSkipGhcCheck = False
         , soptsSkipMsys = configSkipMsys
         , soptsResolveMissingGHC = Nothing
-        , soptsSetupInfoYaml = scoSetupInfoYaml
         , soptsGHCBindistURL = scoGHCBindistURL
-        , soptsGHCJSBootOpts = scoGHCJSBootOpts ++ ["--clean" | scoGHCJSBootClean]
         }
     let compiler = case wantedCompiler of
             WCGhc _ -> "GHC"
diff --git a/src/Stack/SourceMap.hs b/src/Stack/SourceMap.hs
--- a/src/Stack/SourceMap.hs
+++ b/src/Stack/SourceMap.hs
@@ -270,8 +270,10 @@
         prjPkgs <- fmap Map.fromList . for projectPackages $ \resolved -> do
             pp <- mkProjectPackage printWarnings resolved buildHaddocks
             pure (cpName $ ppCommon pp, pp)
+        compiler <- either throwIO pure $ wantedToActual
+                  $ snapshotCompiler snapshot
         return SMActual
-              { smaCompiler = wantedToActual $ snapshotCompiler snapshot
+              { smaCompiler = compiler
               , smaProject = prjPkgs
               , smaDeps = Map.difference deps prjPkgs
               , smaGlobal = globals
diff --git a/src/Stack/Storage/Project.hs b/src/Stack/Storage/Project.hs
--- a/src/Stack/Storage/Project.hs
+++ b/src/Stack/Storage/Project.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DerivingStrategies #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -6,6 +7,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -24,7 +26,6 @@
 
 import qualified Data.ByteString as S
 import qualified Data.Set as Set
-import Database.Persist.Sql (SqlBackend)
 import Database.Persist.Sqlite
 import Database.Persist.TH
 import qualified Pantry.Internal as SQLite
diff --git a/src/Stack/Storage/User.hs b/src/Stack/Storage/User.hs
--- a/src/Stack/Storage/User.hs
+++ b/src/Stack/Storage/User.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DerivingStrategies #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -6,6 +7,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
 {-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TupleSections #-}
 {-# LANGUAGE TypeFamilies #-}
@@ -30,7 +32,6 @@
 import qualified Data.Set as Set
 import qualified Data.Text as T
 import Data.Time.Clock (UTCTime)
-import Database.Persist.Sql (SqlBackend)
 import Database.Persist.Sqlite
 import Database.Persist.TH
 import Distribution.Text (simpleParse, display)
diff --git a/src/Stack/Types/Build.hs b/src/Stack/Types/Build.hs
--- a/src/Stack/Types/Build.hs
+++ b/src/Stack/Types/Build.hs
@@ -53,8 +53,6 @@
 import qualified Data.Map                        as Map
 import qualified Data.Set                        as Set
 import qualified Data.Text                       as T
-import           Data.Text.Encoding              (decodeUtf8With)
-import           Data.Text.Encoding.Error        (lenientDecode)
 import           Database.Persist.Sql            (PersistField(..)
                                                  ,PersistFieldSql(..)
                                                  ,PersistValue(PersistText)
@@ -635,7 +633,6 @@
     , map ("--extra-include-dirs=" ++) (configExtraIncludeDirs config)
     , map ("--extra-lib-dirs=" ++) (configExtraLibDirs config)
     , maybe [] (\customGcc -> ["--with-gcc=" ++ toFilePath customGcc]) (configOverrideGccPath config)
-    , ["--ghcjs" | wc == Ghcjs]
     , ["--exact-configuration"]
     , ["--ghc-option=-fhide-source-paths" | hideSourcePaths cv]
     ]
diff --git a/src/Stack/Types/Compiler.hs b/src/Stack/Types/Compiler.hs
--- a/src/Stack/Types/Compiler.hs
+++ b/src/Stack/Types/Compiler.hs
@@ -10,6 +10,7 @@
   ( ActualCompiler (..)
   , WhichCompiler (..)
   , CompilerRepository (..)
+  , CompilerException (..)
   , defaultCompilerRepository
   , getGhcVersion
   , whichCompiler
@@ -25,7 +26,6 @@
 import           Database.Persist
 import           Database.Persist.Sql
 import qualified Data.Text as T
-import           Data.Text (Text)
 import           Stack.Prelude
 import           Stack.Types.Version
 import           Distribution.Version (mkVersion)
@@ -33,7 +33,6 @@
 -- | Variety of compiler to use.
 data WhichCompiler
     = Ghc
-    | Ghcjs
     deriving (Show, Eq, Ord)
 
 -- | Specifies a compiler and its version number(s).
@@ -43,14 +42,10 @@
 data ActualCompiler
     = ACGhc !Version
     | ACGhcGit !Text !Text
-    | ACGhcjs
-        !Version -- GHCJS version
-        !Version -- GHC version
     deriving (Generic, Show, Eq, Ord, Data, Typeable)
 instance NFData ActualCompiler
 instance Display ActualCompiler where
     display (ACGhc x) = display (WCGhc x)
-    display (ACGhcjs x y) = display (WCGhcjs x y)
     display (ACGhcGit x y) = display (WCGhcGit x y)
 instance ToJSON ActualCompiler where
     toJSON = toJSON . compilerVersionText
@@ -68,18 +63,28 @@
 instance PersistFieldSql ActualCompiler where
   sqlType _ = SqlString
 
-wantedToActual :: WantedCompiler -> ActualCompiler
-wantedToActual (WCGhc x) = ACGhc x
-wantedToActual (WCGhcjs x y) = ACGhcjs x y
-wantedToActual (WCGhcGit x y) = ACGhcGit x y
+data CompilerException
+  = GhcjsNotSupported
+  | PantryException PantryException
 
+instance Show CompilerException where
+    show GhcjsNotSupported = "GHCJS is no longer supported by Stack"
+    show (PantryException p) = displayException p
+instance Exception CompilerException
+
+wantedToActual :: WantedCompiler -> Either CompilerException ActualCompiler
+wantedToActual (WCGhc x) = Right $ ACGhc x
+wantedToActual (WCGhcjs _ _) = Left GhcjsNotSupported
+wantedToActual (WCGhcGit x y) = Right $ ACGhcGit x y
+
 actualToWanted :: ActualCompiler -> WantedCompiler
 actualToWanted (ACGhc x) = WCGhc x
-actualToWanted (ACGhcjs x y) = WCGhcjs x y
 actualToWanted (ACGhcGit x y) = WCGhcGit x y
 
-parseActualCompiler :: T.Text -> Either PantryException ActualCompiler
-parseActualCompiler = fmap wantedToActual . parseWantedCompiler
+parseActualCompiler :: T.Text -> Either CompilerException ActualCompiler
+parseActualCompiler =
+  either (Left . PantryException) wantedToActual .
+  parseWantedCompiler
 
 compilerVersionText :: ActualCompiler -> T.Text
 compilerVersionText = utf8BuilderToText . display
@@ -90,20 +95,16 @@
 whichCompiler :: ActualCompiler -> WhichCompiler
 whichCompiler ACGhc{} = Ghc
 whichCompiler ACGhcGit{} = Ghc
-whichCompiler ACGhcjs{} = Ghcjs
 
 isWantedCompiler :: VersionCheck -> WantedCompiler -> ActualCompiler -> Bool
 isWantedCompiler check (WCGhc wanted) (ACGhc actual) =
     checkVersion check wanted actual
-isWantedCompiler check (WCGhcjs wanted wantedGhc) (ACGhcjs actual actualGhc) =
-    checkVersion check wanted actual && checkVersion check wantedGhc actualGhc
 isWantedCompiler _check (WCGhcGit wCommit wFlavour) (ACGhcGit aCommit aFlavour) =
     wCommit == aCommit && wFlavour == aFlavour
 isWantedCompiler _ _ _ = False
 
 getGhcVersion :: ActualCompiler -> Version
 getGhcVersion (ACGhc v) = v
-getGhcVersion (ACGhcjs _ v) = v
 getGhcVersion (ACGhcGit _ _) =
    -- We can't return the actual version without running the installed ghc.
    -- For now we assume that users of ghc-git use it with a recent commit so we
diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs
--- a/src/Stack/Types/Config.hs
+++ b/src/Stack/Types/Config.hs
@@ -140,7 +140,6 @@
   ,VersionedDownloadInfo(..)
   ,GHCDownloadInfo(..)
   ,SetupInfo(..)
-  ,SetupInfoLocation(..)
   -- ** Docker entrypoint
   ,DockerEntrypoint(..)
   ,DockerUser(..)
@@ -182,14 +181,13 @@
                  (ToJSON, toJSON, FromJSON, FromJSONKey (..), parseJSON, withText, object,
                   (.=), (..:), (...:), (..:?), (..!=), Value(Bool),
                   withObjectWarnings, WarningParser, Object, jsonSubWarnings,
-                  jsonSubWarningsT, jsonSubWarningsTT, WithJSONWarnings(..), noJSONWarnings,
+                  jsonSubWarningsT, jsonSubWarningsTT, WithJSONWarnings(..),
                   FromJSONKeyFunction (FromJSONKeyTextParser))
 import           Data.Attoparsec.Args (parseArgs, EscapingMode (Escaping))
 import qualified Data.ByteArray.Encoding as Mem (convertToBase, Base(Base16))
 import qualified Data.ByteString.Char8 as S8
 import           Data.Coerce (coerce)
 import           Data.List (stripPrefix)
-import           Data.List.NonEmpty (NonEmpty)
 import qualified Data.List.NonEmpty as NonEmpty
 import qualified Data.Map as Map
 import qualified Data.Map.Strict as M
@@ -197,7 +195,6 @@
 import           Data.Monoid.Map (MonoidMap(..))
 import qualified Data.Set as Set
 import qualified Data.Text as T
-import           Data.Text.Encoding (encodeUtf8)
 import           Data.Yaml (ParseException)
 import qualified Data.Yaml as Yaml
 import qualified Distribution.License as C
@@ -209,7 +206,7 @@
 import qualified Distribution.Types.UnqualComponentName as C
 import           Distribution.Version (anyVersion, mkVersion', mkVersion)
 import           Generics.Deriving.Monoid (memptydefault, mappenddefault)
-import           Lens.Micro (Lens', lens, _1, _2, to)
+import           Lens.Micro
 import           Options.Applicative (ReadM)
 import qualified Options.Applicative as OA
 import qualified Options.Applicative.Types as OA
@@ -234,6 +231,7 @@
 import qualified System.FilePath as FilePath
 import           System.PosixCompat.Types (UserID, GroupID, FileMode)
 import           RIO.Process (ProcessContext, HasProcessContext (..))
+import           Casa.Client (CasaRepoPrefix)
 
 -- Re-exports
 import           Stack.Types.Config.Build as X
@@ -283,6 +281,8 @@
          ,configHideTHLoading       :: !Bool
          -- ^ Hide the Template Haskell "Loading package ..." messages from the
          -- console
+         ,configPrefixTimestamps    :: !Bool
+         -- ^ Prefix build output with timestamps for each line.
          ,configPlatform            :: !Platform
          -- ^ The platform we're building for, used in many directory names
          ,configPlatformVariant     :: !PlatformVariant
@@ -331,8 +331,11 @@
          -- ^ Additional GHC options to apply to categories of packages
          ,configCabalConfigOpts     :: !(Map CabalConfigKey [Text])
          -- ^ Additional options to be passed to ./Setup.hs configure
-         ,configSetupInfoLocations  :: ![SetupInfoLocation]
-         -- ^ Additional SetupInfo (inline or remote) to use to find tools.
+         ,configSetupInfoLocations  :: ![String]
+         -- ^ URLs or paths to stack-setup.yaml files, for finding tools.
+         -- If none present, the default setup-info is used.
+         ,configSetupInfoInline     :: !SetupInfo
+         -- ^ Additional SetupInfo to use to find tools.
          ,configPvpBounds           :: !PvpBounds
          -- ^ How PVP upper bounds should be added to packages
          ,configModifyCodePage      :: !Bool
@@ -406,7 +409,7 @@
 instance FromJSONKey CabalConfigKey where
   fromJSONKey = FromJSONKeyTextParser parseCabalConfigKey
 
-parseCabalConfigKey :: Monad m => Text -> m CabalConfigKey
+parseCabalConfigKey :: (Monad m, MonadFail m) => Text -> m CabalConfigKey
 parseCabalConfigKey "$targets" = pure CCKTargets
 parseCabalConfigKey "$locals" = pure CCKLocals
 parseCabalConfigKey "$everything" = pure CCKEverything
@@ -762,6 +765,8 @@
     -- ^ See: 'configConnectionCount'
     , configMonoidHideTHLoading      :: !FirstTrue
     -- ^ See: 'configHideTHLoading'
+    , configMonoidPrefixTimestamps   :: !(First Bool)
+    -- ^ See: 'configPrefixTimestamps'
     , configMonoidLatestSnapshot     :: !(First Text)
     -- ^ See: 'configLatestSnapshot'
     , configMonoidPackageIndices     :: !(First [HackageSecurityConfig])
@@ -816,8 +821,10 @@
     -- ^ See 'configCabalConfigOpts'.
     ,configMonoidExtraPath           :: ![Path Abs Dir]
     -- ^ Additional paths to search for executables in
-    ,configMonoidSetupInfoLocations  :: ![SetupInfoLocation]
-    -- ^ Additional setup info (inline or remote) to use for installing tools
+    ,configMonoidSetupInfoLocations  :: ![String]
+    -- ^ See 'configSetupInfoLocations'
+    ,configMonoidSetupInfoInline     :: !SetupInfo
+    -- ^ See 'configSetupInfoInline'
     ,configMonoidLocalProgramsBase   :: !(First (Path Abs Dir))
     -- ^ Override the default local programs dir, where e.g. GHC is installed.
     ,configMonoidPvpBounds           :: !(First PvpBounds)
@@ -851,6 +858,7 @@
     -- ^ See 'configHideSourcePaths'
     , configMonoidRecommendUpgrade   :: !FirstTrue
     -- ^ See 'configRecommendUpgrade'
+    , configMonoidCasaRepoPrefix     :: !(First CasaRepoPrefix)
     }
   deriving (Show, Generic)
 
@@ -877,6 +885,7 @@
     configMonoidNixOpts <- jsonSubWarnings (obj ..:? configMonoidNixOptsName ..!= mempty)
     configMonoidConnectionCount <- First <$> obj ..:? configMonoidConnectionCountName
     configMonoidHideTHLoading <- FirstTrue <$> obj ..:? configMonoidHideTHLoadingName
+    configMonoidPrefixTimestamps <- First <$> obj ..:? configMonoidPrefixTimestampsName
 
     murls :: Maybe Value <- obj ..:? configMonoidUrlsName
     configMonoidLatestSnapshot <-
@@ -942,8 +951,8 @@
     let configMonoidCabalConfigOpts = coerce (configMonoidCabalConfigOpts' :: Map CabalConfigKey [Text])
 
     configMonoidExtraPath <- obj ..:? configMonoidExtraPathName ..!= []
-    configMonoidSetupInfoLocations <-
-        maybeToList <$> jsonSubWarningsT (obj ..:?  configMonoidSetupInfoLocationsName)
+    configMonoidSetupInfoLocations <- obj ..:? configMonoidSetupInfoLocationsName ..!= []
+    configMonoidSetupInfoInline <- jsonSubWarningsT (obj ..:? configMonoidSetupInfoInlineName) ..!= mempty
     configMonoidLocalProgramsBase <- First <$> obj ..:? configMonoidLocalProgramsBaseName
     configMonoidPvpBounds <- First <$> obj ..:? configMonoidPvpBoundsName
     configMonoidModifyCodePage <- FirstTrue <$> obj ..:? configMonoidModifyCodePageName
@@ -972,9 +981,11 @@
     configMonoidHideSourcePaths <- FirstTrue <$> obj ..:? configMonoidHideSourcePathsName
     configMonoidRecommendUpgrade <- FirstTrue <$> obj ..:? configMonoidRecommendUpgradeName
 
+    configMonoidCasaRepoPrefix <- First <$> obj ..:? configMonoidCasaRepoPrefixName
+
     return ConfigMonoid {..}
   where
-    handleExplicitSetupDep :: Monad m => (Text, Bool) -> m (Maybe PackageName, Bool)
+    handleExplicitSetupDep :: (Monad m, MonadFail m) => (Text, Bool) -> m (Maybe PackageName, Bool)
     handleExplicitSetupDep (name', b) = do
         name <-
             if name' == "*"
@@ -1002,6 +1013,9 @@
 configMonoidHideTHLoadingName :: Text
 configMonoidHideTHLoadingName = "hide-th-loading"
 
+configMonoidPrefixTimestampsName :: Text
+configMonoidPrefixTimestampsName = "build-output-timestamps"
+
 configMonoidUrlsName :: Text
 configMonoidUrlsName = "urls"
 
@@ -1072,8 +1086,11 @@
 configMonoidExtraPathName = "extra-path"
 
 configMonoidSetupInfoLocationsName :: Text
-configMonoidSetupInfoLocationsName = "setup-info"
+configMonoidSetupInfoLocationsName = "setup-info-locations"
 
+configMonoidSetupInfoInlineName :: Text
+configMonoidSetupInfoInlineName = "setup-info"
+
 configMonoidLocalProgramsBaseName :: Text
 configMonoidLocalProgramsBaseName = "local-programs-path"
 
@@ -1128,6 +1145,9 @@
 configMonoidRecommendUpgradeName :: Text
 configMonoidRecommendUpgradeName = "recommend-stack-upgrade"
 
+configMonoidCasaRepoPrefixName :: Text
+configMonoidCasaRepoPrefixName = "casa-repo-prefix"
+
 data ConfigException
   = ParseConfigFileException (Path Abs File) ParseException
   | ParseCustomSnapshotException Text ParseException
@@ -1414,7 +1434,6 @@
     compilerVersion <- view actualCompilerVersionL
     parseRelDir $ case compilerVersion of
         ACGhc version -> versionString version
-        ACGhcjs {} -> compilerVersionString compilerVersion
         ACGhcGit {} -> compilerVersionString compilerVersion
 
 -- | Package database for installing dependencies into
@@ -1663,7 +1682,6 @@
     , siSevenzDll :: Maybe DownloadInfo
     , siMsys2 :: Map Text VersionedDownloadInfo
     , siGHCs :: Map Text (Map Version GHCDownloadInfo)
-    , siGHCJSs :: Map Text (Map ActualCompiler DownloadInfo)
     , siStack :: Map Text (Map Version DownloadInfo)
     }
     deriving Show
@@ -1674,20 +1692,18 @@
         siSevenzDll <- jsonSubWarningsT (o ..:? "sevenzdll-info")
         siMsys2 <- jsonSubWarningsT (o ..:? "msys2" ..!= mempty)
         (fmap unCabalStringMap -> siGHCs) <- jsonSubWarningsTT (o ..:? "ghc" ..!= mempty)
-        siGHCJSs <- jsonSubWarningsTT (o ..:? "ghcjs" ..!= mempty)
         (fmap unCabalStringMap -> siStack) <- jsonSubWarningsTT (o ..:? "stack" ..!= mempty)
         return SetupInfo {..}
 
--- | For @siGHCs@ and @siGHCJSs@ fields maps are deeply merged.
--- For all fields the values from the last @SetupInfo@ win.
+-- | For the @siGHCs@ field maps are deeply merged.
+-- For all fields the values from the first @SetupInfo@ win.
 instance Semigroup SetupInfo where
     l <> r =
         SetupInfo
-        { siSevenzExe = siSevenzExe r <|> siSevenzExe l
-        , siSevenzDll = siSevenzDll r <|> siSevenzDll l
-        , siMsys2 = siMsys2 r <> siMsys2 l
-        , siGHCs = Map.unionWith (<>) (siGHCs r) (siGHCs l)
-        , siGHCJSs = Map.unionWith (<>) (siGHCJSs r) (siGHCJSs l)
+        { siSevenzExe = siSevenzExe l <|> siSevenzExe r
+        , siSevenzDll = siSevenzDll l <|> siSevenzDll r
+        , siMsys2 = siMsys2 l <> siMsys2 r
+        , siGHCs = Map.unionWith (<>) (siGHCs l) (siGHCs r)
         , siStack = Map.unionWith (<>) (siStack l) (siStack r) }
 
 instance Monoid SetupInfo where
@@ -1697,26 +1713,9 @@
         , siSevenzDll = Nothing
         , siMsys2 = Map.empty
         , siGHCs = Map.empty
-        , siGHCJSs = Map.empty
         , siStack = Map.empty
         }
     mappend = (<>)
-
--- | Remote or inline 'SetupInfo'
-data SetupInfoLocation
-    = SetupInfoFileOrURL String
-    | SetupInfoInline SetupInfo
-    deriving (Show)
-
-instance FromJSON (WithJSONWarnings SetupInfoLocation) where
-    parseJSON v =
-        (noJSONWarnings <$>
-         withText "SetupInfoFileOrURL" (pure . SetupInfoFileOrURL . T.unpack) v) <|>
-        inline
-      where
-        inline = do
-            WithJSONWarnings si w <- parseJSON v
-            return $ WithJSONWarnings (SetupInfoInline si) w
 
 -- | How PVP bounds should be added to .cabal files
 data PvpBoundsType
diff --git a/src/Stack/Types/Config/Build.hs b/src/Stack/Types/Config/Build.hs
--- a/src/Stack/Types/Config/Build.hs
+++ b/src/Stack/Types/Config/Build.hs
@@ -339,6 +339,9 @@
     -- ^ Only install packages in the snapshot database, skipping
     -- packages intended for the local database.
     | BSOnlyDependencies
+    | BSOnlyLocals
+    -- ^ Refuse to build anything in the snapshot database, see
+    -- https://github.com/commercialhaskell/stack/issues/5272
     deriving (Show, Eq)
 
 -- | Options for the 'FinalAction' 'DoTests'
diff --git a/src/Stack/Types/Package.hs b/src/Stack/Types/Package.hs
--- a/src/Stack/Types/Package.hs
+++ b/src/Stack/Types/Package.hs
@@ -16,7 +16,7 @@
 import           Data.Aeson (ToJSON (..), FromJSON (..), (.=), (.:), object, withObject)
 import qualified Data.Map as M
 import qualified Data.Set as Set
-import           Distribution.Parsec.Common (PError (..), PWarning (..), showPos)
+import           Distribution.Parsec (PError (..), PWarning (..), showPos)
 import qualified Distribution.SPDX.License as SPDX
 import           Distribution.License (License)
 import           Distribution.ModuleName (ModuleName)
diff --git a/src/Stack/Types/Version.hs b/src/Stack/Types/Version.hs
--- a/src/Stack/Types/Version.hs
+++ b/src/Stack/Types/Version.hs
@@ -11,7 +11,7 @@
   ,IntersectingVersionRange(..)
   ,VersionCheck(..)
   ,versionRangeText
-  ,withinRange
+  ,Cabal.withinRange
   ,Stack.Types.Version.intersectVersionRanges
   ,toMajorVersion
   ,latestApplicableVersion
@@ -24,11 +24,11 @@
 
 import           Stack.Prelude hiding (Vector)
 import           Pantry.Internal.AesonExtended
+import           Data.List (find)
 import qualified Data.Set as Set
 import qualified Data.Text as T
-import           Distribution.Text (disp)
+import           Distribution.Pretty (pretty)
 import qualified Distribution.Version as Cabal
-import           Distribution.Version (Version, versionNumbers, withinRange)
 import qualified Paths_stack as Meta
 import           Text.PrettyPrint (render)
 
@@ -46,7 +46,7 @@
 
 -- | Display a version range
 versionRangeText :: Cabal.VersionRange -> Text
-versionRangeText = T.pack . render . disp
+versionRangeText = T.pack . render . pretty
 
 -- | A modified intersection which also simplifies, for better display.
 intersectVersionRanges :: Cabal.VersionRange -> Cabal.VersionRange -> Cabal.VersionRange
@@ -55,7 +55,7 @@
 -- | Returns the first two components, defaulting to 0 if not present
 toMajorVersion :: Version -> Version
 toMajorVersion v =
-  case versionNumbers v of
+  case Cabal.versionNumbers v of
     []    -> Cabal.mkVersion [0, 0]
     [a]   -> Cabal.mkVersion [a, 0]
     a:b:_ -> Cabal.mkVersion [a, b]
@@ -63,12 +63,12 @@
 -- | Given a version range and a set of versions, find the latest version from
 -- the set that is within the range.
 latestApplicableVersion :: Cabal.VersionRange -> Set Version -> Maybe Version
-latestApplicableVersion r = listToMaybe . filter (`withinRange` r) . Set.toDescList
+latestApplicableVersion r = find (`Cabal.withinRange` r) . Set.toDescList
 
 -- | Get the next major version number for the given version
 nextMajorVersion :: Version -> Version
 nextMajorVersion v =
-  case versionNumbers v of
+  case Cabal.versionNumbers v of
     []    -> Cabal.mkVersion [0, 1]
     [a]   -> Cabal.mkVersion [a, 1]
     a:b:_ -> Cabal.mkVersion [a, b + 1]
@@ -93,7 +93,7 @@
         expected = "VersionCheck value (match-minor, match-exact, or newer-minor)"
 
 checkVersion :: VersionCheck -> Version -> Version -> Bool
-checkVersion check (versionNumbers -> wanted) (versionNumbers -> actual) =
+checkVersion check (Cabal.versionNumbers -> wanted) (Cabal.versionNumbers -> actual) =
     case check of
         MatchMinor -> and (take 3 matching)
         MatchExact -> length wanted == length actual && and matching
@@ -112,7 +112,7 @@
 
 -- | Get minor version (excludes any patchlevel)
 minorVersion :: Version -> Version
-minorVersion = Cabal.mkVersion . take 3 . versionNumbers
+minorVersion = Cabal.mkVersion . take 3 . Cabal.versionNumbers
 
 -- | Current Stack version
 stackVersion :: Version
diff --git a/src/Stack/Unpack.hs b/src/Stack/Unpack.hs
--- a/src/Stack/Unpack.hs
+++ b/src/Stack/Unpack.hs
@@ -38,7 +38,7 @@
     let (errs1, (names, pirs1)) =
           fmap partitionEithers $ partitionEithers $ map parse input
     locs1 <- forM pirs1 $ \pir -> do
-      loc <- completePackageLocation $ RPLIHackage pir Nothing
+      loc <- fmap cplComplete $ completePackageLocation $ RPLIHackage pir Nothing
       pure (loc, packageLocationIdent loc)
     (errs2, locs2) <- partitionEithers <$> traverse toLoc names
     case errs1 ++ errs2 of
@@ -97,7 +97,7 @@
           Nothing ->
             pure $ Left $ "Package does not appear in snapshot: " ++ packageNameString name
           Just sp -> do
-            loc <- completePackageLocation (rspLocation sp)
+            loc <- cplComplete <$> completePackageLocation (rspLocation sp)
             pure $ Right (loc, packageLocationIdent loc)
 
     -- Possible future enhancement: parse names as name + version range
diff --git a/src/Stack/Upgrade.hs b/src/Stack/Upgrade.hs
--- a/src/Stack/Upgrade.hs
+++ b/src/Stack/Upgrade.hs
@@ -12,7 +12,6 @@
 import           Stack.Prelude               hiding (force, Display (..))
 import qualified Data.Text as T
 import           Distribution.Version        (mkVersion')
-import           Lens.Micro                  (set)
 import           Options.Applicative
 import           Path
 import qualified Paths_stack as Paths
@@ -198,7 +197,7 @@
                 -- On Windows 10, an upstream issue with the `git clone` command
                 -- means that command clears, but does not then restore, the
                 -- ENABLE_VIRTUAL_TERMINAL_PROCESSING flag for native terminals.
-                -- The folowing hack re-enables the lost ANSI-capability.
+                -- The following hack re-enables the lost ANSI-capability.
                 when osIsWindows $
                   void $ liftIO $ hSupportsANSIWithoutEmulation stdout
                 return $ Just $ tmp </> relDirStackProgName
diff --git a/src/Stack/Upload.hs b/src/Stack/Upload.hs
--- a/src/Stack/Upload.hs
+++ b/src/Stack/Upload.hs
@@ -27,7 +27,6 @@
 import qualified Data.ByteString.Lazy                  as L
 import qualified Data.Conduit.Binary                   as CB
 import qualified Data.Text                             as T
-import           Data.Text.Encoding                    (encodeUtf8)
 import           Network.HTTP.StackClient              (Request, RequestBody(RequestBodyLBS), Response, withResponse, httpNoBody, getGlobalManager, getResponseStatusCode,
                                                         getResponseBody,
                                                         setRequestHeader,
@@ -39,8 +38,9 @@
 import           Stack.Types.Config
 import           System.Directory                      (createDirectoryIfMissing,
                                                         removeFile, renameFile)
+import           System.Environment                    (lookupEnv)
 import           System.FilePath                       ((</>), takeFileName, takeDirectory)
-import           System.IO                             (stdout, putStrLn, putStr, print) -- TODO remove putStrLn, use logInfo
+import           System.IO                             (putStrLn, putStr, print) -- TODO remove putStrLn, use logInfo
 import           System.PosixCompat.Files              (setFileMode)
 
 -- | Username and password to log into Hackage.
@@ -63,6 +63,9 @@
         <$> o .: "username"
         <*> o .: "password"
 
+withEnvVariable :: Text -> IO Text -> IO Text
+withEnvVariable varName fromPrompt = lookupEnv (T.unpack varName) >>= maybe fromPrompt (pure . T.pack)
+
 -- | Load Hackage credentials, either from a save file or the command
 -- line.
 --
@@ -85,8 +88,8 @@
       return $ mkCreds fp
   where
     fromPrompt fp = do
-      username <- prompt "Hackage username: "
-      password <- promptPassword "Hackage password: "
+      username <- withEnvVariable "HACKAGE_USERNAME" (prompt "Hackage username: ")
+      password <- withEnvVariable "HACKAGE_PASSWORD" (promptPassword "Hackage password: ")
       let hc = HackageCreds
             { hcUsername = username
             , hcPassword = password
diff --git a/src/System/Process/Pager.hs b/src/System/Process/Pager.hs
--- a/src/System/Process/Pager.hs
+++ b/src/System/Process/Pager.hs
@@ -3,49 +3,61 @@
 
 -- | Run external pagers (@$PAGER@, @less@, @more@).
 module System.Process.Pager
-  (pageWriter
-  ,pageText
-  ,PagerException(..))
-  where
+  ( pageWriter
+  , pageText
+  , PagerException (..)
+  ) where
 
 import Stack.Prelude
 import System.Directory (findExecutable)
 import System.Environment (lookupEnv)
-import System.Process (createProcess,shell,waitForProcess,StdStream (CreatePipe)
-                      ,CreateProcess(std_in, close_fds, delegate_ctlc))
-import System.IO (stdout)
+import System.Process ( createProcess, cmdspec, shell, proc, waitForProcess
+                      , CmdSpec (ShellCommand, RawCommand)
+                      , StdStream (CreatePipe)
+                      , CreateProcess (std_in, close_fds, delegate_ctlc)
+                      )
+import Control.Monad.Trans.Maybe (MaybeT (runMaybeT, MaybeT))
 import qualified Data.Text.IO as T
 
 -- | Run pager, providing a function that writes to the pager's input.
 pageWriter :: (Handle -> IO ()) -> IO ()
 pageWriter writer =
-  do mpager <- lookupEnv "PAGER" `orElse`
-               findExecutable "less" `orElse`
-               findExecutable "more"
+  do mpager <- runMaybeT $ cmdspecFromEnvVar
+                       <|> cmdspecFromExeName "less"
+                       <|> cmdspecFromExeName "more"
      case mpager of
        Just pager ->
-         do (Just h,_,_,procHandle) <- createProcess (shell pager)
-                                                       {std_in = CreatePipe
-                                                       ,close_fds = True
-                                                       ,delegate_ctlc = True}
-            (_::Either IOException ()) <- try (do writer h
-                                                  hClose h)
+         do (Just h,_,_,procHandle) <- createProcess pager
+                                         { std_in = CreatePipe
+                                         , close_fds = True
+                                         , delegate_ctlc = True
+                                         }
+            (_ :: Either IOException ()) <- try (do writer h
+                                                    hClose h)
             exit <- waitForProcess procHandle
             case exit of
               ExitSuccess -> return ()
-              ExitFailure n -> throwIO (PagerExitFailure pager n)
+              ExitFailure n -> throwIO (PagerExitFailure (cmdspec pager) n)
             return ()
        Nothing -> writer stdout
   where
-    orElse a b = maybe b (return . Just) =<< a
+    cmdspecFromEnvVar = shell <$> MaybeT (lookupEnv "PAGER")
+    cmdspecFromExeName =
+      fmap (\path -> proc path []) . MaybeT . findExecutable
 
 -- | Run pager to display a 'Text'
 pageText :: Text -> IO ()
 pageText = pageWriter . flip T.hPutStr
 
 -- | Exception running pager.
-data PagerException = PagerExitFailure FilePath Int
+data PagerException = PagerExitFailure CmdSpec Int
   deriving Typeable
 instance Show PagerException where
-  show (PagerExitFailure p n) = "Pager (`" ++ p ++ "') exited with non-zero status: " ++ show n
+  show (PagerExitFailure cmd n) =
+    let
+      getStr (ShellCommand c) = c
+      getStr (RawCommand exePath _) = exePath
+    in
+      "Pager (`" ++ getStr cmd ++ "') exited with non-zero status: " ++ show n
+
 instance Exception PagerException
diff --git a/src/main/Main.hs b/src/main/Main.hs
--- a/src/main/Main.hs
+++ b/src/main/Main.hs
@@ -13,7 +13,6 @@
 import           BuildInfo
 import           Stack.Prelude hiding (Display (..))
 import           Conduit (runConduitRes, sourceLazy, sinkFileCautious)
-import           Control.Monad.Reader (local)
 import           Control.Monad.Trans.Except (ExceptT)
 import           Control.Monad.Writer.Lazy (Writer)
 import           Data.Attoparsec.Args (parseArgs, EscapingMode (Escaping))
@@ -30,7 +29,6 @@
 import           Options.Applicative.Help (errorHelp, stringChunk, vcatChunks)
 import           Options.Applicative.Builder.Extra
 import           Options.Applicative.Complicated
-import           Options.Applicative.Types (ParserHelp(..))
 import           Pantry (loadSnapshot)
 import           Path
 import           Path.IO
@@ -50,7 +48,6 @@
 import           Stack.GhcPkg (findGhcPkgField)
 import qualified Stack.Nix as Nix
 import           Stack.FileWatch
-import           Stack.Freeze
 import           Stack.Ghci
 import           Stack.Hoogle
 import           Stack.Ls
@@ -64,7 +61,6 @@
 import           Stack.Options.ExecParser
 import           Stack.Options.GhciParser
 import           Stack.Options.GlobalParser
-import           Stack.Options.FreezeParser
 
 import           Stack.Options.HpcReportParser
 import           Stack.Options.NewParser
@@ -89,7 +85,7 @@
 import           System.Environment (getProgName, getArgs, withArgs)
 import           System.FilePath (isValid, pathSeparator, takeDirectory)
 import qualified System.FilePath as FP
-import           System.IO (stderr, stdin, stdout, BufferMode(..), hPutStrLn, hGetEncoding, hSetEncoding)
+import           System.IO (hPutStrLn, hGetEncoding, hSetEncoding)
 import           System.Terminal (hIsTerminalDeviceOrMinTTY)
 
 -- | Change the character encoding of the given Handle to transliterate
@@ -334,10 +330,6 @@
                       })
                  (globalOpts OtherCmdGlobalOpts)
                  scriptOptsParser
-      addCommand' "freeze"
-                  "Show project or snapshot with pinned dependencies if there are any such (experimental, may be removed)"
-                  freezeCmd
-                  freezeOptsParser
 
       unless isInterpreter (do
         addCommand' "eval"
@@ -539,11 +531,11 @@
       return (a,(b,mempty))
 
 setupCmd :: SetupCmdOpts -> RIO Runner ()
-setupCmd sco@SetupCmdOpts{..} = withConfig YesReexec $ do
+setupCmd sco@SetupCmdOpts{..} = withConfig YesReexec $ withBuildConfig $ do
   (wantedCompiler, compilerCheck, mstack) <-
     case scoCompilerVersion of
       Just v -> return (v, MatchMinor, Nothing)
-      Nothing -> withBuildConfig $ (,,)
+      Nothing -> (,,)
         <$> view wantedCompilerVersionL
         <*> view (configL.to configCompilerCheck)
         <*> (Just <$> view stackYamlL)
@@ -562,8 +554,8 @@
     exitFailure
   local (over globalOptsL modifyGO) $
     case boptsCLIFileWatch opts of
-      FileWatchPoll -> fileWatchPoll stderr (inner . Just)
-      FileWatch -> fileWatch stderr (inner . Just)
+      FileWatchPoll -> fileWatchPoll (inner . Just)
+      FileWatch -> fileWatch (inner . Just)
       NoFileWatch -> inner Nothing
   where
     inner
@@ -726,8 +718,6 @@
           (ExecCmd cmd, args) -> return (cmd, args)
           (ExecRun, args) -> getRunCmd args
           (ExecGhc, args) -> getGhcCmd eoPackages args
-          -- NOTE: This doesn't work for GHCJS, because it doesn't have
-          -- a runghcjs binary.
           (ExecRunGhc, args) -> getRunGhcCmd eoPackages args
 
       runWithPath eoCwd $ exec cmd args
@@ -759,7 +749,7 @@
           let executables = filter isCExe $ concatMap Set.toList pkgComponents
           let (exe, args') = case args of
                              []   -> (firstExe, args)
-                             x:xs -> case find (\y -> y == (CExe $ T.pack x)) executables of
+                             x:xs -> case find (\y -> y == CExe (T.pack x)) executables of
                                      Nothing -> (firstExe, args)
                                      argExe -> (argExe, xs)
                              where
@@ -867,9 +857,6 @@
           { boptsCLITargets = if hroptsAll hropts then [] else targetNames }
     withConfig YesReexec $ withEnvConfig AllowNoTargets boptsCLI $
         generateHpcReportForTargets hropts tixFiles targetNames
-
-freezeCmd :: FreezeOpts -> RIO Runner ()
-freezeCmd freezeOpts = withConfig YesReexec $ withDefaultEnvConfig $ freeze freezeOpts
 
 data MainException = InvalidReExecVersion String String
                    | InvalidPathForExec FilePath
diff --git a/src/test/Stack/DotSpec.hs b/src/test/Stack/DotSpec.hs
--- a/src/test/Stack/DotSpec.hs
+++ b/src/test/Stack/DotSpec.hs
@@ -19,7 +19,7 @@
 import           Stack.Dot
 
 dummyPayload :: DotPayload
-dummyPayload = DotPayload (parseVersion "0.0.0.0") (Just (Right BSD3))
+dummyPayload = DotPayload (parseVersion "0.0.0.0") (Just (Right BSD3)) Nothing
 
 spec :: Spec
 spec = do
@@ -53,14 +53,14 @@
 
     prop "requested packages are pruned" $ do
       let resolvedGraph = runIdentity (resolveDependencies Nothing graph stubLoader)
-          allPackages g = Map.keysSet g `Set.union`  fold (fmap fst g)
+          allPackages g = Map.keysSet g `Set.union` foldMap fst g
       forAll (sublistOf (Set.toList (allPackages resolvedGraph))) $ \toPrune ->
         let pruned = pruneGraph [pkgName "one", pkgName "two"] toPrune resolvedGraph
         in Set.null (allPackages pruned `Set.intersection` Set.fromList toPrune)
 
     prop "pruning removes orhpans" $ do
       let resolvedGraph = runIdentity (resolveDependencies Nothing graph stubLoader)
-          allPackages g = Map.keysSet g `Set.union` fold (fmap fst g)
+          allPackages g = Map.keysSet g `Set.union` foldMap fst g
           orphans g = Map.filterWithKey (\k _ -> not (graphElem k g)) g
       forAll (sublistOf (Set.toList (allPackages resolvedGraph))) $ \toPrune ->
         let pruned = pruneGraph [pkgName "one", pkgName "two"] toPrune resolvedGraph
diff --git a/src/test/Stack/LockSpec.hs b/src/test/Stack/LockSpec.hs
--- a/src/test/Stack/LockSpec.hs
+++ b/src/test/Stack/LockSpec.hs
@@ -5,7 +5,6 @@
 module Stack.LockSpec where
 
 import Pantry.Internal.AesonExtended (WithJSONWarnings(..))
-import Data.ByteString (ByteString)
 import qualified Data.Yaml as Yaml
 import Distribution.Types.PackageName (mkPackageName)
 import Distribution.Types.Version (mkVersion)
@@ -44,9 +43,9 @@
                 [r|#some
 snapshots:
 - completed:
-    compiler: ghc-8.2.2
+    compiler: ghc-8.6.5
   original:
-    compiler: ghc-8.2.2
+    compiler: ghc-8.6.5
 packages: []
 |]
         pkgImm <- lckPkgImmutableLocations <$> decodeLocked lockFile
@@ -60,11 +59,11 @@
     size: 527801
     url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/11/22.yaml
     sha256: 7c8b1853da784bd7beb8728168bf4e879d8a2f6daf408ca0fa7933451864a96a
-  original: lts-11.22
+  original: lts-14.27
 - completed:
-    compiler: ghc-8.2.2
+    compiler: ghc-8.6.5
   original:
-    compiler: ghc-8.2.2
+    compiler: ghc-8.6.5
 packages: []
 |]
         pkgImm <- lckPkgImmutableLocations <$> decodeLocked lockFile
@@ -78,11 +77,11 @@
     size: 527801
     url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/11/22.yaml
     sha256: 7c8b1853da784bd7beb8728168bf4e879d8a2f6daf408ca0fa7933451864a96a
-  original: lts-11.22
+  original: lts-14.27
 - completed:
-    compiler: ghc-8.2.2
+    compiler: ghc-8.6.5
   original:
-    compiler: ghc-8.2.2
+    compiler: ghc-8.6.5
 packages:
 - original:
     subdir: wai
@@ -90,9 +89,6 @@
     commit: d11d63f1a6a92db8c637a8d33e7953ce6194a3e0
   completed:
     subdir: wai
-    cabal-file:
-      size: 1765
-      sha256: eea52c4967d8609c2f79213d6dffe6d6601034f1471776208404781de7051410
     name: wai
     version: 3.2.1.2
     git: https://github.com/yesodweb/wai.git
@@ -106,9 +102,6 @@
     commit: d11d63f1a6a92db8c637a8d33e7953ce6194a3e0
   completed:
     subdir: warp
-    cabal-file:
-      size: 10725
-      sha256: cfec5336260bb4b1ecbd833f7d6948fd1ee373770471fe79796cf9c389c71758
     name: warp
     version: 3.2.25
     git: https://github.com/yesodweb/wai.git
@@ -128,7 +121,6 @@
             emptyRPM = RawPackageMetadata { rpmName = Nothing
                                           , rpmVersion = Nothing
                                           , rpmTreeKey = Nothing
-                                          , rpmCabal = Nothing
                                           }
         pkgImm `shouldBe`
             [ LockedLocation
@@ -145,10 +137,6 @@
                                            (decodeSHA
                                              "ecfd0b4b75f435a3f362394807b35e5ef0647b1a25005d44a3632c49db4833d2")
                                            (FileSize 714))
-                                     , pmCabal =
-                                         toBlobKey
-                                         "eea52c4967d8609c2f79213d6dffe6d6601034f1471776208404781de7051410"
-                                         1765
                                      }))
             , LockedLocation
               (RPLIRepo (waiSubdirRepo "warp") emptyRPM)
@@ -164,9 +152,5 @@
                                         (decodeSHA
                                           "f808e075811b002563d24c393ce115be826bb66a317d38da22c513ee42b7443a")
                                         (FileSize 5103))
-                                    , pmCabal =
-                                      toBlobKey
-                                      "cfec5336260bb4b1ecbd833f7d6948fd1ee373770471fe79796cf9c389c71758"
-                                      10725
                                     }))
             ]
diff --git a/src/unix/System/Terminal.hsc b/src/unix/System/Terminal.hsc
--- a/src/unix/System/Terminal.hsc
+++ b/src/unix/System/Terminal.hsc
@@ -1,9 +1,40 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
 module System.Terminal
 ( fixCodePage
+, getTerminalWidth
 , hIsTerminalDeviceOrMinTTY
 ) where
 
+import           Foreign
+import           Foreign.C.Types
 import           RIO (MonadIO, Handle, hIsTerminalDevice)
+
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+
+newtype WindowWidth = WindowWidth CUShort
+    deriving (Eq, Ord, Show)
+
+instance Storable WindowWidth where
+  sizeOf _ = (#size struct winsize)
+  alignment _ = (#alignment struct winsize)
+  peek p = WindowWidth <$> (#peek struct winsize, ws_col) p
+  poke p (WindowWidth w) = do
+    (#poke struct winsize, ws_col) p w
+
+foreign import ccall "sys/ioctl.h ioctl"
+  ioctl :: CInt -> CInt -> Ptr WindowWidth -> IO CInt
+
+getTerminalWidth :: IO (Maybe Int)
+getTerminalWidth =
+    alloca $ \p -> do
+        errno <- ioctl (#const STDOUT_FILENO) (#const TIOCGWINSZ) p
+        if errno < 0
+        then return Nothing
+        else do
+            WindowWidth w <- peek p
+            return . Just . fromIntegral $ w
 
 fixCodePage :: x -> y -> a -> a
 fixCodePage _ _ = id
diff --git a/src/windows/System/Terminal.hs b/src/windows/System/Terminal.hs
--- a/src/windows/System/Terminal.hs
+++ b/src/windows/System/Terminal.hs
@@ -1,14 +1,73 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 module System.Terminal
 ( fixCodePage
+, getTerminalWidth
 , hIsTerminalDeviceOrMinTTY
 ) where
 
 import Distribution.Types.Version (mkVersion)
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.Marshal.Alloc
 import Stack.Prelude
+import System.IO hiding (hIsTerminalDevice)
+import System.Process
 import System.Win32 (isMinTTYHandle, withHandleToHANDLE)
 import System.Win32.Console (setConsoleCP, setConsoleOutputCP, getConsoleCP, getConsoleOutputCP)
+import RIO.Partial (read)
+
+type HANDLE = Ptr ()
+
+data CONSOLE_SCREEN_BUFFER_INFO
+
+sizeCONSOLE_SCREEN_BUFFER_INFO :: Int
+sizeCONSOLE_SCREEN_BUFFER_INFO = 22
+
+posCONSOLE_SCREEN_BUFFER_INFO_srWindow :: Int
+posCONSOLE_SCREEN_BUFFER_INFO_srWindow = 10 -- 4 x Word16 Left,Top,Right,Bottom
+
+c_STD_OUTPUT_HANDLE :: Int
+c_STD_OUTPUT_HANDLE = -11
+
+foreign import ccall unsafe "windows.h GetConsoleScreenBufferInfo"
+    c_GetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO Bool
+
+foreign import ccall unsafe "windows.h GetStdHandle"
+    c_GetStdHandle :: Int -> IO HANDLE
+
+
+getTerminalWidth :: IO (Maybe Int)
+getTerminalWidth = do
+    hdl <- c_GetStdHandle c_STD_OUTPUT_HANDLE
+    allocaBytes sizeCONSOLE_SCREEN_BUFFER_INFO $ \p -> do
+        b <- c_GetConsoleScreenBufferInfo hdl p
+        if not b
+            then do -- This could happen on Cygwin or MSYS
+                let stty = (shell "stty size") { 
+                      std_in  = UseHandle stdin
+                    , std_out = CreatePipe
+                    , std_err = CreatePipe
+                    }
+                (_, mbStdout, _, rStty) <- createProcess stty
+                exStty <- waitForProcess rStty
+                case exStty of
+                    ExitFailure _ -> return Nothing
+                    ExitSuccess ->
+                        maybe (return Nothing)
+                              (\hSize -> do
+                                  sizeStr <- hGetContents hSize
+                                  case map read $ words sizeStr :: [Int] of
+                                    [_r, c] -> return $ Just c
+                                    _ -> return Nothing
+                              )
+                              mbStdout
+            else do
+                [left,_top,right,_bottom] <- forM [0..3] $ \i -> do
+                    v <- peekByteOff p ((i*2) + posCONSOLE_SCREEN_BUFFER_INFO_srWindow)
+                    return $ fromIntegral (v :: Word16)
+                return $ Just (1+right-left)
 
 -- | Set the code page for this process as necessary. Only applies to Windows.
 -- See: https://github.com/commercialhaskell/stack/issues/738
diff --git a/stack.cabal b/stack.cabal
--- a/stack.cabal
+++ b/stack.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.0
 name: stack
-version: 2.1.3.1
+version: 2.3.1
 license: BSD3
 license-file: LICENSE
 maintainer: manny@fpcomplete.com
@@ -28,7 +28,6 @@
     ChangeLog.md
     README.md
     stack.yaml
-    snapshot.yaml
     doc/azure_ci.md
     doc/build_command.md
     doc/build_overview.md
@@ -67,9 +66,9 @@
     location: https://github.com/commercialhaskell/stack
 
 custom-setup
-    setup-depends: Cabal >=2.4.0.1,
+    setup-depends: Cabal >=3.0.0.0,
                    base >=4.10 && <5,
-                   filepath >=1.4.1.2
+                   filepath >=1.4.2.1
 
 flag disable-git-info
     description:
@@ -137,7 +136,6 @@
         Stack.Docker
         Stack.Dot
         Stack.FileWatch
-        Stack.Freeze
         Stack.GhcPkg
         Stack.Ghci
         Stack.Ghci.Script
@@ -157,7 +155,6 @@
         Stack.Options.DockerParser
         Stack.Options.DotParser
         Stack.Options.ExecParser
-        Stack.Options.FreezeParser
         Stack.Options.GhcBuildParser
         Stack.Options.GhciParser
         Stack.Options.GhcVariantParser
@@ -213,6 +210,7 @@
         Paths_stack
     hs-source-dirs: src/
     other-modules:
+        Path.Extended
         Stack.Types.Cache
     autogen-modules:
         Paths_stack
@@ -221,96 +219,95 @@
                  -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path
                  -fwarn-identities
     build-depends:
-        Cabal >=2.4.0.1,
-        aeson >=1.2.4.0,
+        Cabal >=3.0.0.0,
+        aeson >=1.4.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9,
-        array >=0.5.2.0,
-        async >=2.1.1.1,
-        attoparsec >=0.13.2.2,
+        ansi-terminal >=0.9.1,
+        array >=0.5.3.0,
+        async >=2.2.2,
+        attoparsec >=0.13.2.3,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.1,
+        base64-bytestring >=1.0.0.3,
         bytestring >=0.10.8.2,
-        colour >=2.3.4,
-        conduit >=1.3.0.3,
-        conduit-extra >=1.3.0,
-        containers >=0.5.10.2,
+        casa-client >=0.0.1,
+        casa-types >=0.0.1,
+        colour >=2.3.5,
+        conduit >=1.3.1.2,
+        conduit-extra >=1.3.4,
+        containers >=0.6.0.1,
         cryptonite >=0.25,
         cryptonite-conduit >=0.2.2,
-        deepseq >=1.4.3.0,
-        directory >=1.3.0.2,
+        deepseq >=1.4.4.0,
+        directory >=1.3.3.0,
         echo >=0.1.3,
-        exceptions >=0.8.3,
-        extra >=1.6.9,
-        file-embed >=0.0.10.1,
-        filelock >=0.1.1.2,
-        filepath >=1.4.1.2,
+        exceptions >=0.10.4,
+        extra >=1.6.19,
+        file-embed >=0.0.11.1,
+        filelock >=0.1.1.4,
+        filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.2,
+        generic-deriving >=1.12.4,
         hackage-security >=0.5.3.0,
         hashable >=1.2.7.0,
         hi-file-parser >=0.1.0.0,
-        hpack >=0.31.2,
+        hpack >=0.33.0,
         hpc >=0.6.0.3,
-        http-client >=0.5.13.1,
+        http-client >=0.6.4,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.2,
-        http-download >=0.1.0.0,
-        http-types >=0.12.1,
-        memory >=0.14.16,
-        microlens >=0.4.8.3,
+        http-conduit >=2.3.7.3,
+        http-download >=0.2.0.0,
+        http-types >=0.12.3,
+        memory >=0.14.18,
+        microlens >=0.4.10,
         mintty >=0.1.2,
-        mono-traversable >=1.0.9.0,
+        mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
-        mustache >=2.3.0,
-        neat-interpolation >=0.3.2.1,
-        network-uri >=2.6.1.0,
+        mustache >=2.3.1,
+        neat-interpolation >=0.3.2.6,
+        network-uri >=2.6.2.0,
         open-browser >=0.2.1.0,
-        optparse-applicative >=0.14.2.0,
-        pantry >=0.1.1.1,
+        optparse-applicative >=0.14.3.0,
+        pantry >=0.4.0.1,
         path >=0.6.1,
-        path-io >=1.3.3,
+        path-io >=1.4.2,
         persistent >=2.9.2,
         persistent-sqlite >=2.9.3,
-        persistent-template >=2.5.4,
-        pretty >=1.1.3.3,
+        persistent-template >=2.6.0,
+        pretty >=1.1.3.6,
         primitive >=0.6.4.0,
-        process >=1.6.3.0,
+        process >=1.6.5.0,
         project-template >=0.2.0.1,
         regex-applicative-text >=0.1.0.1,
-        resource-pool >=0.2.3.2,
-        resourcet >=1.2.1,
-        retry >=0.7.6.3,
-        rio >=0.1.11.0,
+        retry >=0.8.1.0,
+        rio >=0.1.14.0,
         rio-prettyprint >=0.1.0.0,
         semigroups >=0.18.5,
         split >=0.2.3.3,
-        stm >=2.4.5.0,
-        streaming-commons >=0.1.19,
-        tar >=0.5.1.0,
-        template-haskell >=2.12.0.0,
-        temporary >=1.2.1.1,
-        terminal-size >=0.3.2.1,
-        text >=1.2.3.0,
+        stm >=2.5.0.0,
+        streaming-commons >=0.2.1.2,
+        tar >=0.5.1.1,
+        template-haskell >=2.14.0.0,
+        temporary >=1.3,
+        text >=1.2.3.1,
         text-metrics >=0.3.0,
-        th-reify-many >=0.1.8,
+        th-reify-many >=0.1.9,
         time >=1.8.0.2,
         tls >=1.4.1,
-        transformers >=0.5.2.0,
+        transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.4,
-        unix-compat >=0.5.0.1,
+        unicode-transforms >=0.3.6,
+        unix-compat >=0.5.2,
         unliftio >=0.2.12,
-        unordered-containers >=0.2.9.0,
-        vector >=0.12.0.1,
-        yaml >=0.10.4.0,
-        zip-archive >=0.3.3,
-        zlib >=0.6.2
+        unordered-containers >=0.2.10.0,
+        vector >=0.12.1.2,
+        yaml >=0.11.2.0,
+        zip-archive >=0.4.1,
+        zlib >=0.6.2.1
     
     if os(windows)
         cpp-options: -DWINDOWS
         build-depends:
-            Win32 -any
+            Win32 >=2.6.1.0
     else
         build-tools: hsc2hs -any
         build-depends:
@@ -342,97 +339,96 @@
                  -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path
                  -threaded -rtsopts
     build-depends:
-        Cabal >=2.4.0.1,
-        aeson >=1.2.4.0,
+        Cabal >=3.0.0.0,
+        aeson >=1.4.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9,
-        array >=0.5.2.0,
-        async >=2.1.1.1,
-        attoparsec >=0.13.2.2,
+        ansi-terminal >=0.9.1,
+        array >=0.5.3.0,
+        async >=2.2.2,
+        attoparsec >=0.13.2.3,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.1,
+        base64-bytestring >=1.0.0.3,
         bytestring >=0.10.8.2,
-        colour >=2.3.4,
-        conduit >=1.3.0.3,
-        conduit-extra >=1.3.0,
-        containers >=0.5.10.2,
+        casa-client >=0.0.1,
+        casa-types >=0.0.1,
+        colour >=2.3.5,
+        conduit >=1.3.1.2,
+        conduit-extra >=1.3.4,
+        containers >=0.6.0.1,
         cryptonite >=0.25,
         cryptonite-conduit >=0.2.2,
-        deepseq >=1.4.3.0,
-        directory >=1.3.0.2,
+        deepseq >=1.4.4.0,
+        directory >=1.3.3.0,
         echo >=0.1.3,
-        exceptions >=0.8.3,
-        extra >=1.6.9,
-        file-embed >=0.0.10.1,
-        filelock >=0.1.1.2,
-        filepath >=1.4.1.2,
+        exceptions >=0.10.4,
+        extra >=1.6.19,
+        file-embed >=0.0.11.1,
+        filelock >=0.1.1.4,
+        filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.2,
+        generic-deriving >=1.12.4,
         hackage-security >=0.5.3.0,
         hashable >=1.2.7.0,
         hi-file-parser >=0.1.0.0,
-        hpack >=0.31.2,
+        hpack >=0.33.0,
         hpc >=0.6.0.3,
-        http-client >=0.5.13.1,
+        http-client >=0.6.4,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.2,
-        http-download >=0.1.0.0,
-        http-types >=0.12.1,
-        memory >=0.14.16,
-        microlens >=0.4.8.3,
+        http-conduit >=2.3.7.3,
+        http-download >=0.2.0.0,
+        http-types >=0.12.3,
+        memory >=0.14.18,
+        microlens >=0.4.10,
         mintty >=0.1.2,
-        mono-traversable >=1.0.9.0,
+        mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
-        mustache >=2.3.0,
-        neat-interpolation >=0.3.2.1,
-        network-uri >=2.6.1.0,
+        mustache >=2.3.1,
+        neat-interpolation >=0.3.2.6,
+        network-uri >=2.6.2.0,
         open-browser >=0.2.1.0,
-        optparse-applicative >=0.14.2.0,
-        pantry >=0.1.1.1,
+        optparse-applicative >=0.14.3.0,
+        pantry >=0.4.0.1,
         path >=0.6.1,
-        path-io >=1.3.3,
+        path-io >=1.4.2,
         persistent >=2.9.2,
         persistent-sqlite >=2.9.3,
-        persistent-template >=2.5.4,
-        pretty >=1.1.3.3,
+        persistent-template >=2.6.0,
+        pretty >=1.1.3.6,
         primitive >=0.6.4.0,
-        process >=1.6.3.0,
+        process >=1.6.5.0,
         project-template >=0.2.0.1,
         regex-applicative-text >=0.1.0.1,
-        resource-pool >=0.2.3.2,
-        resourcet >=1.2.1,
-        retry >=0.7.6.3,
-        rio >=0.1.11.0,
+        retry >=0.8.1.0,
+        rio >=0.1.14.0,
         rio-prettyprint >=0.1.0.0,
         semigroups >=0.18.5,
         split >=0.2.3.3,
         stack -any,
-        stm >=2.4.5.0,
-        streaming-commons >=0.1.19,
-        tar >=0.5.1.0,
-        template-haskell >=2.12.0.0,
-        temporary >=1.2.1.1,
-        terminal-size >=0.3.2.1,
-        text >=1.2.3.0,
+        stm >=2.5.0.0,
+        streaming-commons >=0.2.1.2,
+        tar >=0.5.1.1,
+        template-haskell >=2.14.0.0,
+        temporary >=1.3,
+        text >=1.2.3.1,
         text-metrics >=0.3.0,
-        th-reify-many >=0.1.8,
+        th-reify-many >=0.1.9,
         time >=1.8.0.2,
         tls >=1.4.1,
-        transformers >=0.5.2.0,
+        transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.4,
-        unix-compat >=0.5.0.1,
+        unicode-transforms >=0.3.6,
+        unix-compat >=0.5.2,
         unliftio >=0.2.12,
-        unordered-containers >=0.2.9.0,
-        vector >=0.12.0.1,
-        yaml >=0.10.4.0,
-        zip-archive >=0.3.3,
-        zlib >=0.6.2
+        unordered-containers >=0.2.10.0,
+        vector >=0.12.1.2,
+        yaml >=0.11.2.0,
+        zip-archive >=0.4.1,
+        zlib >=0.6.2.1
     
     if os(windows)
         cpp-options: -DWINDOWS
         build-depends:
-            Win32 -any
+            Win32 >=2.6.1.0
     else
         build-tools: hsc2hs -any
         build-depends:
@@ -444,8 +440,8 @@
     if !flag(disable-git-info)
         cpp-options: -DUSE_GIT_INFO
         build-depends:
-            githash >=0.1.3.0,
-            optparse-simple >=0.1.0
+            githash >=0.1.3.3,
+            optparse-simple >=0.1.1.2
     
     if flag(hide-dependency-versions)
         cpp-options: -DHIDE_DEP_VERSIONS
@@ -464,98 +460,97 @@
                  -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path
                  -threaded -rtsopts -with-rtsopts=-N
     build-depends:
-        Cabal >=2.4.0.1,
-        aeson >=1.2.4.0,
+        Cabal >=3.0.0.0,
+        aeson >=1.4.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9,
-        array >=0.5.2.0,
-        async >=2.1.1.1,
-        attoparsec >=0.13.2.2,
+        ansi-terminal >=0.9.1,
+        array >=0.5.3.0,
+        async >=2.2.2,
+        attoparsec >=0.13.2.3,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.1,
+        base64-bytestring >=1.0.0.3,
         bytestring >=0.10.8.2,
-        colour >=2.3.4,
-        conduit >=1.3.0.3,
-        conduit-extra >=1.3.0,
-        containers >=0.5.10.2,
+        casa-client >=0.0.1,
+        casa-types >=0.0.1,
+        colour >=2.3.5,
+        conduit >=1.3.1.2,
+        conduit-extra >=1.3.4,
+        containers >=0.6.0.1,
         cryptonite >=0.25,
         cryptonite-conduit >=0.2.2,
-        deepseq >=1.4.3.0,
-        directory >=1.3.0.2,
+        deepseq >=1.4.4.0,
+        directory >=1.3.3.0,
         echo >=0.1.3,
-        exceptions >=0.8.3,
-        extra >=1.6.9,
-        file-embed >=0.0.10.1,
-        filelock >=0.1.1.2,
-        filepath >=1.4.1.2,
+        exceptions >=0.10.4,
+        extra >=1.6.19,
+        file-embed >=0.0.11.1,
+        filelock >=0.1.1.4,
+        filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.2,
+        generic-deriving >=1.12.4,
         hackage-security >=0.5.3.0,
         hashable >=1.2.7.0,
         hi-file-parser >=0.1.0.0,
-        hpack >=0.31.2,
+        hpack >=0.33.0,
         hpc >=0.6.0.3,
-        hspec >=2.4.8,
-        http-client >=0.5.13.1,
+        hspec >=2.7.1,
+        http-client >=0.6.4,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.2,
-        http-download >=0.1.0.0,
-        http-types >=0.12.1,
-        memory >=0.14.16,
-        microlens >=0.4.8.3,
+        http-conduit >=2.3.7.3,
+        http-download >=0.2.0.0,
+        http-types >=0.12.3,
+        memory >=0.14.18,
+        microlens >=0.4.10,
         mintty >=0.1.2,
-        mono-traversable >=1.0.9.0,
+        mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
-        mustache >=2.3.0,
-        neat-interpolation >=0.3.2.1,
-        network-uri >=2.6.1.0,
+        mustache >=2.3.1,
+        neat-interpolation >=0.3.2.6,
+        network-uri >=2.6.2.0,
         open-browser >=0.2.1.0,
-        optparse-applicative >=0.14.2.0,
-        optparse-generic >=1.3.0,
-        pantry >=0.1.1.1,
+        optparse-applicative >=0.14.3.0,
+        optparse-generic >=1.3.1,
+        pantry >=0.4.0.1,
         path >=0.6.1,
-        path-io >=1.3.3,
+        path-io >=1.4.2,
         persistent >=2.9.2,
         persistent-sqlite >=2.9.3,
-        persistent-template >=2.5.4,
-        pretty >=1.1.3.3,
+        persistent-template >=2.6.0,
+        pretty >=1.1.3.6,
         primitive >=0.6.4.0,
-        process >=1.6.3.0,
+        process >=1.6.5.0,
         project-template >=0.2.0.1,
         regex-applicative-text >=0.1.0.1,
-        resource-pool >=0.2.3.2,
-        resourcet >=1.2.1,
-        retry >=0.7.6.3,
-        rio >=0.1.11.0,
+        retry >=0.8.1.0,
+        rio >=0.1.14.0,
         rio-prettyprint >=0.1.0.0,
         semigroups >=0.18.5,
         split >=0.2.3.3,
-        stm >=2.4.5.0,
-        streaming-commons >=0.1.19,
-        tar >=0.5.1.0,
-        template-haskell >=2.12.0.0,
-        temporary >=1.2.1.1,
-        terminal-size >=0.3.2.1,
-        text >=1.2.3.0,
+        stm >=2.5.0.0,
+        streaming-commons >=0.2.1.2,
+        tar >=0.5.1.1,
+        template-haskell >=2.14.0.0,
+        temporary >=1.3,
+        text >=1.2.3.1,
         text-metrics >=0.3.0,
-        th-reify-many >=0.1.8,
+        th-reify-many >=0.1.9,
         time >=1.8.0.2,
         tls >=1.4.1,
-        transformers >=0.5.2.0,
+        transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.4,
-        unix-compat >=0.5.0.1,
+        unicode-transforms >=0.3.6,
+        unix-compat >=0.5.2,
         unliftio >=0.2.12,
-        unordered-containers >=0.2.9.0,
-        vector >=0.12.0.1,
-        yaml >=0.10.4.0,
-        zip-archive >=0.3.3,
-        zlib >=0.6.2
+        unordered-containers >=0.2.10.0,
+        vector >=0.12.1.2,
+        yaml >=0.11.2.0,
+        zip-archive >=0.4.1,
+        zlib >=0.6.2.1
     
     if os(windows)
         cpp-options: -DWINDOWS
         build-depends:
-            Win32 -any
+            Win32 >=2.6.1.0
     else
         build-tools: hsc2hs -any
         build-depends:
@@ -563,6 +558,9 @@
     
     if !flag(integration-tests)
         buildable: False
+    
+    if flag(static)
+        ld-options: -static -pthread
 
 test-suite stack-test
     type: exitcode-stdio-1.0
@@ -589,101 +587,100 @@
                  -fwarn-incomplete-record-updates -optP-Wno-nonportable-include-path
                  -threaded
     build-depends:
-        Cabal >=2.4.0.1,
-        QuickCheck >=2.10.1,
-        aeson >=1.2.4.0,
+        Cabal >=3.0.0.0,
+        QuickCheck >=2.13.2,
+        aeson >=1.4.6.0,
         annotated-wl-pprint >=0.7.0,
-        ansi-terminal >=0.9,
-        array >=0.5.2.0,
-        async >=2.1.1.1,
-        attoparsec >=0.13.2.2,
+        ansi-terminal >=0.9.1,
+        array >=0.5.3.0,
+        async >=2.2.2,
+        attoparsec >=0.13.2.3,
         base >=4.10 && <5,
-        base64-bytestring >=1.0.0.1,
+        base64-bytestring >=1.0.0.3,
         bytestring >=0.10.8.2,
-        colour >=2.3.4,
-        conduit >=1.3.0.3,
-        conduit-extra >=1.3.0,
-        containers >=0.5.10.2,
+        casa-client >=0.0.1,
+        casa-types >=0.0.1,
+        colour >=2.3.5,
+        conduit >=1.3.1.2,
+        conduit-extra >=1.3.4,
+        containers >=0.6.0.1,
         cryptonite >=0.25,
         cryptonite-conduit >=0.2.2,
-        deepseq >=1.4.3.0,
-        directory >=1.3.0.2,
+        deepseq >=1.4.4.0,
+        directory >=1.3.3.0,
         echo >=0.1.3,
-        exceptions >=0.8.3,
-        extra >=1.6.9,
-        file-embed >=0.0.10.1,
-        filelock >=0.1.1.2,
-        filepath >=1.4.1.2,
+        exceptions >=0.10.4,
+        extra >=1.6.19,
+        file-embed >=0.0.11.1,
+        filelock >=0.1.1.4,
+        filepath >=1.4.2.1,
         fsnotify >=0.3.0.1,
-        generic-deriving >=1.12.2,
+        generic-deriving >=1.12.4,
         hackage-security >=0.5.3.0,
         hashable >=1.2.7.0,
         hi-file-parser >=0.1.0.0,
-        hpack >=0.31.2,
+        hpack >=0.33.0,
         hpc >=0.6.0.3,
-        hspec >=2.4.8,
-        http-client >=0.5.13.1,
+        hspec >=2.7.1,
+        http-client >=0.6.4,
         http-client-tls >=0.3.5.3,
-        http-conduit >=2.3.2,
-        http-download >=0.1.0.0,
-        http-types >=0.12.1,
-        memory >=0.14.16,
-        microlens >=0.4.8.3,
+        http-conduit >=2.3.7.3,
+        http-download >=0.2.0.0,
+        http-types >=0.12.3,
+        memory >=0.14.18,
+        microlens >=0.4.10,
         mintty >=0.1.2,
-        mono-traversable >=1.0.9.0,
+        mono-traversable >=1.0.15.1,
         mtl >=2.2.2,
-        mustache >=2.3.0,
-        neat-interpolation >=0.3.2.1,
-        network-uri >=2.6.1.0,
+        mustache >=2.3.1,
+        neat-interpolation >=0.3.2.6,
+        network-uri >=2.6.2.0,
         open-browser >=0.2.1.0,
-        optparse-applicative >=0.14.2.0,
-        pantry >=0.1.1.1,
+        optparse-applicative >=0.14.3.0,
+        pantry >=0.4.0.1,
         path >=0.6.1,
-        path-io >=1.3.3,
+        path-io >=1.4.2,
         persistent >=2.9.2,
         persistent-sqlite >=2.9.3,
-        persistent-template >=2.5.4,
-        pretty >=1.1.3.3,
+        persistent-template >=2.6.0,
+        pretty >=1.1.3.6,
         primitive >=0.6.4.0,
-        process >=1.6.3.0,
+        process >=1.6.5.0,
         project-template >=0.2.0.1,
         raw-strings-qq >=1.1,
         regex-applicative-text >=0.1.0.1,
-        resource-pool >=0.2.3.2,
-        resourcet >=1.2.1,
-        retry >=0.7.6.3,
-        rio >=0.1.11.0,
+        retry >=0.8.1.0,
+        rio >=0.1.14.0,
         rio-prettyprint >=0.1.0.0,
         semigroups >=0.18.5,
         smallcheck >=1.1.5,
         split >=0.2.3.3,
         stack -any,
-        stm >=2.4.5.0,
-        streaming-commons >=0.1.19,
-        tar >=0.5.1.0,
-        template-haskell >=2.12.0.0,
-        temporary >=1.2.1.1,
-        terminal-size >=0.3.2.1,
-        text >=1.2.3.0,
+        stm >=2.5.0.0,
+        streaming-commons >=0.2.1.2,
+        tar >=0.5.1.1,
+        template-haskell >=2.14.0.0,
+        temporary >=1.3,
+        text >=1.2.3.1,
         text-metrics >=0.3.0,
-        th-reify-many >=0.1.8,
+        th-reify-many >=0.1.9,
         time >=1.8.0.2,
         tls >=1.4.1,
-        transformers >=0.5.2.0,
+        transformers >=0.5.6.2,
         typed-process >=0.2.6.0,
-        unicode-transforms >=0.3.4,
-        unix-compat >=0.5.0.1,
+        unicode-transforms >=0.3.6,
+        unix-compat >=0.5.2,
         unliftio >=0.2.12,
-        unordered-containers >=0.2.9.0,
-        vector >=0.12.0.1,
-        yaml >=0.10.4.0,
-        zip-archive >=0.3.3,
-        zlib >=0.6.2
+        unordered-containers >=0.2.10.0,
+        vector >=0.12.1.2,
+        yaml >=0.11.2.0,
+        zip-archive >=0.4.1,
+        zlib >=0.6.2.1
     
     if os(windows)
         cpp-options: -DWINDOWS
         build-depends:
-            Win32 -any
+            Win32 >=2.6.1.0
     else
         build-tools: hsc2hs -any
         build-depends:
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,12 +1,14 @@
-resolver: snapshot.yaml
+resolver: lts-14.27
 
 packages:
 - .
 
 docker:
   enable: false
-  repo: fpco/stack-build:lts-11.22
 
+  #image: fpco/alpine-haskell-stack:8.6.5
+  image: fpco/alpine-haskell-stack@sha256:49e7e15f3b1d3f882ba5bb701463b1d508fbf40e5aafce6ea31acd210da570ba
+
 nix:
   # --nix on the command-line to enable.
   packages:
@@ -19,3 +21,16 @@
 
 ghc-options:
    "$locals": -fhide-source-paths
+
+extra-deps:
+- Cabal-3.0.0.0@rev:0
+- hpack-0.33.0@rev:0
+- http-download-0.2.0.0@rev:0
+- filelock-0.1.1.4@rev:0
+- pantry-0.4.0.1@rev:0
+- casa-client-0.0.1@rev:0
+- casa-types-0.0.1@rev:0
+
+drop-packages:
+# See https://github.com/commercialhaskell/stack/pull/4712
+- cabal-install
diff --git a/test/integration/lib/StackTest.hs b/test/integration/lib/StackTest.hs
--- a/test/integration/lib/StackTest.hs
+++ b/test/integration/lib/StackTest.hs
@@ -270,7 +270,7 @@
 -- the main @stack.yaml@.
 --
 defaultResolverArg :: String
-defaultResolverArg = "--resolver=lts-11.22"
+defaultResolverArg = "--resolver=lts-14.27"
 
 -- | Remove a file and ignore any warnings about missing files.
 removeFileIgnore :: HasCallStack => FilePath -> IO ()
