Skip to content

Commit

Permalink
Merge pull request #6117 from commercialhaskell/fix5203
Browse files Browse the repository at this point in the history
Fix #5203 Put GHCi configuration scripts in a user-specific location
  • Loading branch information
mpilgrem committed May 10, 2023
2 parents 805e1ef + 30ed862 commit dfd5c82
Show file tree
Hide file tree
Showing 22 changed files with 71 additions and 39 deletions.
6 changes: 6 additions & 0 deletions ChangeLog.md
Expand Up @@ -10,6 +10,12 @@ Major changes:

Behavior changes:

* Use `$XDG_CACHE_HOME/stack/ghci-script`, rather than `<temp>/haskell-stack-ghci`
(where `<temp>` is the directory yielded by the `temporary` package's
`System.IO.Temp.getCanonicalTemporaryDirectory`), as the base location for
GHCi script files generated by `stack ghci` or `stack repl`. See
[#5203](https://github.com/commercialhaskell/stack/issues/5203)

Other enhancements:

Bug fixes:
Expand Down
8 changes: 8 additions & 0 deletions doc/ghci.md
Expand Up @@ -29,6 +29,14 @@ but not another is quite likely to cause failures. GHCi will be run with
`-XNoImplicitPrelude`, but it is likely that modules in the other component
assume that the `Prelude` is implicitly imported.

`stack ghci` configures GHCi by using a GHCi script file. Such files are located
in subdirectories of `<XDG_CACHE_HOME>/stack/ghci-script`, where
`<XDG_CACHE_HOME>` refers to the
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
for user-specific non-essential (cached) data. On Unix-like operating systems,
the default for `<XDG_CACHE_HOME>` is `$HOME/.cache`. On Windows, the default
is `%LOCALAPPDATA%`.

## Selecting Main module

When loading multiple packages, there may be multiple definitions for the `Main`
Expand Down
1 change: 0 additions & 1 deletion package.yaml
Expand Up @@ -125,7 +125,6 @@ dependencies:
- streaming-commons
- tar
- template-haskell
- temporary
- text
- text-metrics
- th-reify-many
Expand Down
1 change: 1 addition & 0 deletions src/Data/Attoparsec/Interpreter.hs
Expand Up @@ -61,6 +61,7 @@ import Conduit ( decodeUtf8C, withSourceFile )
import Data.Conduit.Attoparsec ( ParseError (..), Position (..), sinkParserEither )
import Data.List ( intercalate )
import Data.Text ( pack )
import Stack.Constants ( stackProgName )
import Stack.Prelude
import System.FilePath ( takeExtension )
import System.IO ( hPutStrLn )
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Build/Execute.hs
Expand Up @@ -113,7 +113,7 @@ import Stack.Constants
, relDirSetupExeCache, relDirSetupExeSrc, relFileBuildLock
, relFileConfigure, relFileSetupHs, relFileSetupLhs
, relFileSetupLower, relFileSetupMacrosH, setupGhciShimCode
, testGhcEnvRelFile
, stackProgName, testGhcEnvRelFile
)
import Stack.Constants.Config
( distDirFromDir, distRelativeDir, hpcDirFromDir
Expand Down
4 changes: 2 additions & 2 deletions src/Stack/Config.hs
Expand Up @@ -85,8 +85,8 @@ import Stack.Constants
, platformVariantEnvVar, relDirBin, relDirStackWork
, relFileReadmeTxt, relFileStorage, relDirPantry
, relDirPrograms, relDirStackProgName, relDirUpperPrograms
, stackDeveloperModeDefault, stackDotYaml, stackRootEnvVar
, stackWorkEnvVar, stackXdgEnvVar
, stackDeveloperModeDefault, stackDotYaml, stackProgName
, stackRootEnvVar, stackWorkEnvVar, stackXdgEnvVar
)
import Stack.Lock ( lockCachedWanted )
import Stack.Prelude
Expand Down
20 changes: 16 additions & 4 deletions src/Stack/Constants.hs
Expand Up @@ -10,6 +10,8 @@ module Stack.Constants
, buildPlanCacheDir
, haskellFileExts
, haskellDefaultPreprocessorExts
, stackProgName
, stackProgName'
, stackDotYaml
, stackWorkEnvVar
, stackRootEnvVar
Expand Down Expand Up @@ -44,6 +46,8 @@ module Stack.Constants
, relFileCabalMacrosH
, relDirBuild
, relDirBin
, relDirGhci
, relDirGhciScript
, relDirPantry
, relDirPrograms
, relDirUpperPrograms
Expand Down Expand Up @@ -88,7 +92,6 @@ module Stack.Constants
, relDirAll
, relFilePackageCache
, relFileDockerfile
, relDirHaskellStackGhci
, relFileGhciScript
, relDirCombined
, relFileHpcIndexHtml
Expand Down Expand Up @@ -134,10 +137,12 @@ import Data.ByteString.Builder ( byteString )
import Data.Char ( toUpper )
import Data.FileEmbed ( embedFile, makeRelativeToProject )
import qualified Data.Set as Set
import qualified Data.Text as T
import Distribution.Package ( mkPackageName )
import Hpack.Config ( packageConfig )
import qualified Language.Haskell.TH.Syntax as TH ( runIO, lift )
import Path ( (</>), mkRelDir, mkRelFile, parseAbsFile )
import Stack.Constants.StackProgName ( stackProgName )
import Stack.Constants.UsrLibDirs ( usrLibDirs )
import Stack.Prelude
import Stack.Types.Compiler ( WhichCompiler (..) )
Expand All @@ -154,6 +159,10 @@ instance Exception ConstantsException where
displayException WiredInPackagesNotParsedBug = bugReport "[S-6057]"
"Parse error in wiredInPackages."

-- | Name of the Stack program.
stackProgName' :: Text
stackProgName' = T.pack stackProgName

-- | Extensions used for Haskell modules. Excludes preprocessor ones.
haskellFileExts :: [Text]
haskellFileExts = ["hs", "hsc", "lhs"]
Expand Down Expand Up @@ -357,6 +366,12 @@ relDirBuild = $(mkRelDir "build")
relDirBin :: Path Rel Dir
relDirBin = $(mkRelDir "bin")

relDirGhci :: Path Rel Dir
relDirGhci = $(mkRelDir "ghci")

relDirGhciScript :: Path Rel Dir
relDirGhciScript = $(mkRelDir "ghci-script")

relDirPantry :: Path Rel Dir
relDirPantry = $(mkRelDir "pantry")

Expand Down Expand Up @@ -493,9 +508,6 @@ relFilePackageCache = $(mkRelFile "package.cache")
relFileDockerfile :: Path Rel File
relFileDockerfile = $(mkRelFile "Dockerfile")

relDirHaskellStackGhci :: Path Rel Dir
relDirHaskellStackGhci = $(mkRelDir "haskell-stack-ghci")

relFileGhciScript :: Path Rel File
relFileGhciScript = $(mkRelFile "ghci-script")

Expand Down
9 changes: 5 additions & 4 deletions src/Stack/Constants/Config.hs
Expand Up @@ -24,7 +24,8 @@ module Stack.Constants.Config
) where

import Path ( (</>), mkRelDir, mkRelFile, parseRelDir )
import Stack.Constants ( cabalPackageName )
import Stack.Constants
( cabalPackageName, relDirDist, relDirGhci, relDirHpc )
import Stack.Prelude
import Stack.Types.BuildConfig ( HasBuildConfig, projectRootL )
import Stack.Types.CompilerPaths ( cabalVersionL )
Expand All @@ -44,7 +45,7 @@ ghciDirL :: HasBuildConfig env => Getting r env (Path Abs Dir)
ghciDirL = to $ \env -> -- FIXME is this idiomatic lens code?
let workDir = view workDirL env
root = view projectRootL env
in root </> workDir </> $(mkRelDir "ghci/")
in root </> workDir </> relDirGhci

-- | The directory containing the files used for dirtiness check of source files.
buildCachesDir :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
Expand Down Expand Up @@ -112,7 +113,7 @@ hpcDirFromDir fp =
hpcRelativeDir :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
=> m (Path Rel Dir)
hpcRelativeDir =
fmap (</> $(mkRelDir "hpc")) distRelativeDir
fmap (</> relDirHpc) distRelativeDir

-- | Package's setup-config storing Cabal configuration
setupConfigFromDir :: (MonadThrow m, MonadReader env m, HasEnvConfig env)
Expand Down Expand Up @@ -145,7 +146,7 @@ rootDistRelativeDir ::
=> m (Path Rel Dir)
rootDistRelativeDir = do
workDir <- view workDirL
pure $ workDir </> $(mkRelDir "dist")
pure $ workDir </> relDirDist

-- | Package's working directory.
workDirFromDir :: (MonadReader env m, HasConfig env)
Expand Down
14 changes: 14 additions & 0 deletions src/Stack/Constants/StackProgName.hs
@@ -0,0 +1,14 @@
{-# LANGUAGE NoImplicitPrelude #-}

module Stack.Constants.StackProgName
( stackProgName
) where

import Stack.Prelude ( String )

-- | Name of the Stack program.

-- NOTE: Defined in this module rather than in "Stack.Constants", due to
-- GHC stage restrictions and the use of Template Haskell.
stackProgName :: String
stackProgName = "stack"
15 changes: 7 additions & 8 deletions src/Stack/Ghci.hs
Expand Up @@ -25,9 +25,10 @@ import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TLE
import qualified Distribution.PackageDescription as C
import Path ((</>), parent, parseAbsDir, parseRelFile )
import Path ((</>), parent, parseRelFile )
import Path.Extra ( forgivingResolveFile', toFilePathNoTrailingSep )
import Path.IO ( doesFileExist, ensureDir )
import Path.IO
( XdgDirectory (..), doesFileExist, ensureDir, getXdgDir )
import RIO.Process
( HasProcessContext, exec, proc, readProcess_
, withWorkingDir
Expand All @@ -38,8 +39,8 @@ import Stack.Build.Source
( getLocalFlags, localDependencies, projectLocalPackages )
import Stack.Build.Target ( NeedTargets (..), parseTargets )
import Stack.Constants
( relDirHaskellStackGhci, relFileCabalMacrosH
, relFileGhciScript
( relDirGhciScript, relDirStackProgName, relFileCabalMacrosH
, relFileGhciScript, stackProgName'
)
import Stack.Constants.Config ( ghciDirL, objectInterfaceDirL )
import Stack.Ghci.Script
Expand Down Expand Up @@ -85,7 +86,6 @@ import Stack.Types.SourceMap
, SMTargets (..), SMWanted (..), SourceMap (..), Target (..)
)
import System.IO ( putStrLn )
import System.IO.Temp ( getCanonicalTemporaryDirectory )
import System.Permissions ( setScriptPerms )

-- | Type representing exceptions thrown by functions exported by the
Expand Down Expand Up @@ -566,9 +566,8 @@ runGhci GhciOpts{..} targets mainFile pkgs extraFiles exposePackages = do
-- file names are determined by hashing. This also has the nice side
-- effect of making it possible to copy the ghci invocation out of
-- the log and have it still work.
tmpDirectory <-
(</> relDirHaskellStackGhci) <$>
(parseAbsDir =<< liftIO getCanonicalTemporaryDirectory)
tmpDirectory <- getXdgDir XdgCache $
Just (relDirStackProgName </> relDirGhciScript)
ghciDir <- view ghciDirL
ensureDir ghciDir
ensureDir tmpDirectory
Expand Down
1 change: 1 addition & 0 deletions src/Stack/Hoogle.hs
Expand Up @@ -19,6 +19,7 @@ import qualified RIO.Map as Map
import RIO.Process ( findExecutable, proc, readProcess_, runProcess_)
import qualified Stack.Build ( build )
import Stack.Build.Target ( NeedTargets (NeedTargets) )
import Stack.Constants ( stackProgName' )
import Stack.Prelude
import Stack.Runners
( ShouldReexec (..), withConfig, withDefaultEnvConfig
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Init.hs
Expand Up @@ -41,7 +41,7 @@ import Stack.BuildPlan
, removeSrcPkgDefaultFlags, selectBestSnapshot
)
import Stack.Config ( getSnapshots, makeConcreteResolver )
import Stack.Constants ( stackDotYaml )
import Stack.Constants ( stackDotYaml, stackProgName' )
import Stack.Prelude
import Stack.Runners
( ShouldReexec (..), withConfig, withGlobalProject )
Expand Down
1 change: 1 addition & 0 deletions src/Stack/Options/DockerParser.hs
Expand Up @@ -17,6 +17,7 @@ import Options.Applicative.Builder.Extra
, firstBoolFlagsFalse, firstBoolFlagsNoDefault
, firstBoolFlagsTrue, optionalFirst
)
import Stack.Constants ( stackProgName )
import Stack.Docker ( dockerCmdName )
import Stack.Prelude
import Stack.Options.Utils ( hideMods )
Expand Down
12 changes: 0 additions & 12 deletions src/Stack/Prelude.hs
Expand Up @@ -13,8 +13,6 @@ module Stack.Prelude
, prompt
, promptPassword
, promptBool
, stackProgName
, stackProgName'
, FirstTrue (..)
, fromFirstTrue
, defaultFirstTrue
Expand Down Expand Up @@ -259,16 +257,6 @@ promptBool txt = liftIO $ do
T.putStrLn "Please press either 'y' or 'n', and then enter."
promptBool txt

-- | Name of the 'stack' program.
--
-- NOTE: Should be defined in "Stack.Constants", but not doing so due to the
-- GHC stage restrictions.
stackProgName :: String
stackProgName = "stack"

stackProgName' :: Text
stackProgName' = T.pack stackProgName

-- | Like @First Bool@, but the default is @True@.
newtype FirstTrue
= FirstTrue { getFirstTrue :: Maybe Bool }
Expand Down
1 change: 1 addition & 0 deletions src/Stack/SDist.hs
Expand Up @@ -51,6 +51,7 @@ import Stack.Build.Execute
)
import Stack.Build.Installed ( getInstalled, toInstallMap )
import Stack.Build.Source ( projectLocalPackages )
import Stack.Constants ( stackProgName, stackProgName' )
import Stack.Constants.Config ( distDirFromDir )
import Stack.Package
( PackageDescriptionPair (..), resolvePackage
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/Setup.hs
Expand Up @@ -93,7 +93,7 @@ import Stack.Constants
, relFileLibgmpSo3, relFileLibncurseswSo6, relFileLibtinfoSo5
, relFileLibtinfoSo6, relFileMainHs, relFileStack
, relFileStackDotExe, relFileStackDotTmp
, relFileStackDotTmpDotExe, usrLibDirs
, relFileStackDotTmpDotExe, stackProgName, usrLibDirs
)
import Stack.Constants.Config ( distRelativeDir )
import Stack.GhcPkg
Expand Down
1 change: 1 addition & 0 deletions src/Stack/SourceMap.hs
Expand Up @@ -31,6 +31,7 @@ import qualified Pantry.SHA256 as SHA256
import qualified RIO.Map as Map
import RIO.Process ( HasProcessContext )
import qualified RIO.Set as Set
import Stack.Constants ( stackProgName' )
import Stack.PackageDump ( conduitDumpPackage, ghcPkgDump )
import Stack.Prelude
import Stack.Types.Build.Exception ( BuildPrettyException (..) )
Expand Down
1 change: 1 addition & 0 deletions src/Stack/Types/Docker.hs
Expand Up @@ -50,6 +50,7 @@ import Distribution.Version ( anyVersion )
import Generics.Deriving.Monoid ( mappenddefault, memptydefault )
import Pantry.Internal.AesonExtended
import Path
import Stack.Constants ( stackProgName )
import Stack.Prelude hiding ( Display (..) )
import Stack.Types.Version
import Text.Read ( Read (..) )
Expand Down
1 change: 1 addition & 0 deletions src/main/Main.hs
Expand Up @@ -10,6 +10,7 @@ import BuildInfo ( versionString' )
import GHC.IO.Encoding ( mkTextEncoding, textEncodingName )
import Options.Applicative.Builder.Extra ( execExtraHelp )
import Stack.CLI ( commandLineHandler )
import Stack.Constants ( stackProgName )
import Stack.Docker ( dockerCmdName, dockerHelpOptName )
import Stack.Nix ( nixCmdName, nixHelpOptName )
import Stack.Options.DockerParser ( dockerOptsParser )
Expand Down
2 changes: 1 addition & 1 deletion src/main/Stack/CLI.hs
Expand Up @@ -21,7 +21,7 @@ import RIO.Process ( withProcessContextNoLogging )
import Stack.Build ( buildCmd )
import Stack.Clean ( CleanCommand (..), cleanCmd )
import Stack.ConfigCmd as ConfigCmd
import Stack.Constants ( globalFooter )
import Stack.Constants ( globalFooter, stackProgName )
import Stack.Coverage ( hpcReportCmd )
import Stack.Docker
( dockerCmdName, dockerHelpOptName, dockerPullCmdName )
Expand Down
1 change: 1 addition & 0 deletions src/test/Stack/ArgsSpec.hs
Expand Up @@ -14,6 +14,7 @@ import Data.Attoparsec.Interpreter ( interpreterArgsParser )
import qualified Data.Attoparsec.Text as P
import Data.Text ( pack )
import Prelude ( head )
import Stack.Constants ( stackProgName )
import Stack.Prelude
import Test.Hspec ( Spec, describe, it )

Expand Down
5 changes: 1 addition & 4 deletions stack.cabal
Expand Up @@ -308,6 +308,7 @@ library
other-modules:
Path.Extended
Stack.ComponentFile
Stack.Constants.StackProgName
Stack.Internal.BuildInfo
Stack.PackageFile
Stack.Types.Cache
Expand Down Expand Up @@ -388,7 +389,6 @@ library
, streaming-commons
, tar
, template-haskell
, temporary
, text
, text-metrics
, th-reify-many
Expand Down Expand Up @@ -522,7 +522,6 @@ executable stack
, streaming-commons
, tar
, template-haskell
, temporary
, text
, text-metrics
, th-reify-many
Expand Down Expand Up @@ -649,7 +648,6 @@ executable stack-integration-test
, streaming-commons
, tar
, template-haskell
, temporary
, text
, text-metrics
, th-reify-many
Expand Down Expand Up @@ -784,7 +782,6 @@ test-suite stack-test
, streaming-commons
, tar
, template-haskell
, temporary
, text
, text-metrics
, th-reify-many
Expand Down

0 comments on commit dfd5c82

Please sign in to comment.