summaryrefslogtreecommitdiff
path: root/ghc/GHCi
diff options
context:
space:
mode:
authorFraser Tweedale <frase@frase.id.au>2019-04-10 21:53:08 +1000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-04-15 06:26:37 -0400
commit71cf94db8445e5d8225ce65a9feecbfaa3ac3fe3 (patch)
treeb5d60858c3639a439da3bfb4b21dc328988f4f19 /ghc/GHCi
parent4b1ef06d45fb3cd226b5ec4217e975d48b85e645 (diff)
downloadhaskell-71cf94db8445e5d8225ce65a9feecbfaa3ac3fe3.tar.gz
GHCi: fix load order of .ghci files
Directives in .ghci files in the current directory ("local .ghci") can be overridden by global files. Change the order in which the configs are loaded: global and $HOME/.ghci first, then local. Also introduce a new field to GHCiState to control whether local .ghci gets sourced or ignored. This commit does not add a way to set this value (a subsequent commit will add this), but the .ghci sourcing routine respects its value. Fixes: https://gitlab.haskell.org/ghc/ghc/issues/14689 Related: https://gitlab.haskell.org/ghc/ghc/issues/6017 Related: https://gitlab.haskell.org/ghc/ghc/issues/14250
Diffstat (limited to 'ghc/GHCi')
-rw-r--r--ghc/GHCi/UI.hs44
-rw-r--r--ghc/GHCi/UI/Monad.hs11
2 files changed, 46 insertions, 9 deletions
diff --git a/ghc/GHCi/UI.hs b/ghc/GHCi/UI.hs
index e386fe6058..55d06dcc1e 100644
--- a/ghc/GHCi/UI.hs
+++ b/ghc/GHCi/UI.hs
@@ -102,7 +102,7 @@ import Data.Char
import Data.Function
import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef )
import Data.List ( find, group, intercalate, intersperse, isPrefixOf, nub,
- partition, sort, sortBy )
+ partition, sort, sortBy, (\\) )
import qualified Data.Set as S
import Data.Maybe
import Data.Map (Map)
@@ -482,6 +482,7 @@ interactiveUI config srcs maybe_exprs = do
stop = default_stop,
editor = default_editor,
options = [],
+ localConfig = SourceLocalConfig,
-- We initialize line number as 0, not 1, because we use
-- current line number while reporting errors which is
-- incremented after reading a line.
@@ -566,8 +567,6 @@ runGHCi paths maybe_exprs = do
let
ignore_dot_ghci = gopt Opt_IgnoreDotGhci dflags
- current_dir = return (Just ".ghci")
-
app_user_dir = liftIO $ withGhcAppData
(\dir -> return (Just (dir </> "ghci.conf")))
(return Nothing)
@@ -606,17 +605,44 @@ runGHCi paths maybe_exprs = do
setGHCContextFromGHCiState
- dot_cfgs <- if ignore_dot_ghci then return [] else do
- dot_files <- catMaybes <$> sequence [ current_dir, app_user_dir, home_dir ]
- liftIO $ filterM checkFileAndDirPerms dot_files
- mdot_cfgs <- liftIO $ mapM canonicalizePath' dot_cfgs
+ processedCfgs <- if ignore_dot_ghci
+ then pure []
+ else do
+ userCfgs <- do
+ paths <- catMaybes <$> sequence [ app_user_dir, home_dir ]
+ checkedPaths <- liftIO $ filterM checkFileAndDirPerms paths
+ liftIO . fmap (nub . catMaybes) $ mapM canonicalizePath' checkedPaths
+
+ localCfg <- do
+ let path = ".ghci"
+ ok <- liftIO $ checkFileAndDirPerms path
+ if ok then liftIO $ canonicalizePath' path else pure Nothing
+
+ mapM_ sourceConfigFile userCfgs
+ -- Process the global and user .ghci
+ -- (but not $CWD/.ghci or CLI args, yet)
+
+ behaviour <- localConfig <$> getGHCiState
+
+ processedLocalCfg <- case localCfg of
+ Just path | path `notElem` userCfgs ->
+ -- don't read .ghci twice if CWD is $HOME
+ case behaviour of
+ SourceLocalConfig -> localCfg <$ sourceConfigFile path
+ IgnoreLocalConfig -> pure Nothing
+ _ -> pure Nothing
+
+ pure $ maybe id (:) processedLocalCfg userCfgs
let arg_cfgs = reverse $ ghciScripts dflags
-- -ghci-script are collected in reverse order
-- We don't require that a script explicitly added by -ghci-script
-- is owned by the current user. (#6017)
- mapM_ sourceConfigFile $ nub $ (catMaybes mdot_cfgs) ++ arg_cfgs
- -- nub, because we don't want to read .ghci twice if the CWD is $HOME.
+
+ mapM_ sourceConfigFile $ nub arg_cfgs \\ processedCfgs
+ -- Dedup, and remove any configs we already processed.
+ -- Importantly, if $PWD/.ghci was ignored due to configuration,
+ -- explicitly specifying it does cause it to be processed.
-- Perform a :load for files given on the GHCi command line
-- When in -e mode, if the load fails then we want to stop
diff --git a/ghc/GHCi/UI/Monad.hs b/ghc/GHCi/UI/Monad.hs
index 16bcd20ee4..696303b949 100644
--- a/ghc/GHCi/UI/Monad.hs
+++ b/ghc/GHCi/UI/Monad.hs
@@ -15,6 +15,7 @@ module GHCi.UI.Monad (
GHCiState(..), GhciMonad(..),
GHCiOption(..), isOptionSet, setOption, unsetOption,
Command(..), CommandResult(..), cmdSuccess,
+ LocalConfigBehaviour(..),
PromptFunction,
BreakLocation(..),
TickArray,
@@ -79,6 +80,7 @@ data GHCiState = GHCiState
prompt_cont :: PromptFunction,
editor :: String,
stop :: String,
+ localConfig :: LocalConfigBehaviour,
options :: [GHCiOption],
line_number :: !Int, -- ^ input line
break_ctr :: !Int,
@@ -197,6 +199,15 @@ data GHCiOption
-- modules after load
deriving Eq
+-- | Treatment of ./.ghci files. For now we either load or
+-- ignore. But later we could implement a "safe mode" where
+-- only safe operations are performed.
+--
+data LocalConfigBehaviour
+ = SourceLocalConfig
+ | IgnoreLocalConfig
+ deriving (Eq)
+
data BreakLocation
= BreakLocation
{ breakModule :: !GHC.Module