packages feed

directory 1.3.9.0 → 1.3.10.0

raw patch · 7 files changed

+90/−39 lines, 7 filesdep ~Win32dep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: Win32, base

API changes (from Hackage documentation)

+ System.Directory: getExecSearchPath :: IO [FilePath]
+ System.Directory.OsPath: getExecSearchPath :: IO [OsPath]
- System.Directory.Internal: ListT :: m (Maybe (a, ListT m a)) -> ListT m a
+ System.Directory.Internal: ListT :: m (Maybe (a, ListT m a)) -> ListT (m :: Type -> Type) a
- System.Directory.Internal: [unListT] :: ListT m a -> m (Maybe (a, ListT m a))
+ System.Directory.Internal: [unListT] :: ListT (m :: Type -> Type) a -> m (Maybe (a, ListT m a))
- System.Directory.Internal: data () => OsString
+ System.Directory.Internal: data OsString
- System.Directory.Internal: emptyListT :: Applicative m => ListT m a
+ System.Directory.Internal: emptyListT :: forall (m :: Type -> Type) a. Applicative m => ListT m a
- System.Directory.Internal: listToListT :: Applicative m => [a] -> ListT m a
+ System.Directory.Internal: listToListT :: forall (m :: Type -> Type) a. Applicative m => [a] -> ListT m a
- System.Directory.Internal: newtype ListT m a
+ System.Directory.Internal: newtype ListT (m :: Type -> Type) a

Files

System/Directory.hs view
@@ -40,6 +40,9 @@     , getUserDocumentsDirectory     , getTemporaryDirectory +    -- * PATH+    , getExecSearchPath+     -- * Actions on files     , removeFile     , renameFile@@ -1337,3 +1340,7 @@ -} getTemporaryDirectory :: IO FilePath getTemporaryDirectory = D.getTemporaryDirectory >>= decodeFS++-- | Get the contents of the @PATH@ environment variable.+getExecSearchPath :: IO [FilePath]+getExecSearchPath = D.getExecSearchPath >>= (`for` decodeFS)
System/Directory/Internal/Posix.hsc view
@@ -148,6 +148,9 @@     path <- getPath     pure (findExecutablesInDirectoriesLazy path binary) +getPath :: IO [OsPath]+getPath = splitSearchPath <$> getEnvOs (os "PATH")+ exeExtensionInternal :: OsString exeExtensionInternal = exeExtension @@ -390,10 +393,6 @@           Nothing           Nothing     Just value -> pure value---- | Get the contents of the @PATH@ environment variable.-getPath :: IO [OsPath]-getPath = splitSearchPath <$> getEnvOs (os "PATH")  -- | $HOME is preferred, because the user has control over it. However, POSIX -- doesn't define it as a mandatory variable, so fall back to `getpwuid_r`.
System/Directory/Internal/Windows.hsc view
@@ -4,7 +4,7 @@ #if defined(mingw32_HOST_OS) ##if defined(i386_HOST_ARCH) ## define WINAPI stdcall-##elif defined(x86_64_HOST_ARCH)+##elif defined(x86_64_HOST_ARCH) || defined(aarch64_HOST_ARCH) ## define WINAPI ccall ##else ## error unknown architecture@@ -29,6 +29,7 @@   , pack   , pathSeparator   , splitDirectories+  , splitSearchPath   , takeExtension   , toChar   , unpack@@ -41,6 +42,7 @@ import qualified System.Win32.WindowsString.Shell as Win32 import qualified System.Win32.WindowsString.Time as Win32 import qualified System.Win32.WindowsString.Types as Win32+import qualified System.Win32.WindowsString.Console as Win32  type RawHandle = OsPath @@ -53,6 +55,26 @@ closeRaw :: RawHandle -> IO () closeRaw _ = pure () +lookupEnvOs :: OsString -> IO (Maybe OsString)+lookupEnvOs (OsString name) = (OsString <$>) <$> Win32.getEnv name++getEnvOs :: OsString -> IO OsString+getEnvOs name = do+  env <- lookupEnvOs name+  case env of+    Nothing ->+      throwIO $+        mkIOError+          doesNotExistErrorType+          ("env var " <> show name <> " not found")+          Nothing+          Nothing+    Just value -> pure value++-- | Get the contents of the @PATH@ environment variable.+getPath :: IO [OsPath]+getPath = splitSearchPath <$> getEnvOs (os "PATH")+ createDirectoryInternal :: OsPath -> IO () createDirectoryInternal path =   (`ioeSetOsPath` path) `modifyIOError` do@@ -665,24 +687,6 @@ setAccessPermissions :: OsPath -> Permissions -> IO () setAccessPermissions path Permissions{writable = w} = do   setFilePermissions path (setWriteMode w 0)--lookupEnvOs :: OsString -> IO (Maybe OsString)-lookupEnvOs (OsString name) = do-  result <--    Win32.withTString name $ \ pName ->-    peekTStringWith 256 $ \ pBuffer size ->-    c_GetEnvironmentVariable pName pBuffer size-  case result of-    Left errCode | errCode == win32_eRROR_ENVVAR_NOT_FOUND -> pure Nothing-                 | otherwise -> Win32.failWith "GetEnvironmentVariable" errCode-    Right value -> pure (Just (OsString value))--foreign import WINAPI unsafe "windows.h GetEnvironmentVariableW"-  c_GetEnvironmentVariable-    :: Win32.LPWSTR-    -> Win32.LPWSTR-    -> Win32.DWORD-    -> IO Win32.DWORD  getFolderPath :: Win32.CSIDL -> IO OsPath getFolderPath what = OsString <$> Win32.sHGetFolderPath nullPtr what nullPtr 0
System/Directory/OsPath.hs view
@@ -42,6 +42,9 @@     , getUserDocumentsDirectory     , getTemporaryDirectory +    -- * PATH+    , getExecSearchPath+     -- * Actions on files     , removeFile     , renameFile@@ -1653,3 +1656,7 @@ -} getTemporaryDirectory :: IO OsPath getTemporaryDirectory = getTemporaryDirectoryInternal++-- | Get the contents of the @PATH@ environment variable.+getExecSearchPath :: IO [OsPath]+getExecSearchPath = getPath
changelog.md view
@@ -1,6 +1,12 @@ Changelog for the [`directory`][1] package ========================================== +## 1.3.10.0 (Dec 2025)++  * Add `getExecSearchPath` as replacement for+    `System.FilePath.getSearchPath`.+    ([#198](https://github.com/haskell/directory/pull/198))+ ## 1.3.9.0 (Oct 2024)    * Rely on `file-io` for file I/O.
directory.cabal view
@@ -1,6 +1,6 @@ cabal-version:  2.2 name:           directory-version:        1.3.9.0+version:        1.3.10.0 license:        BSD-3-Clause license-file:   LICENSE maintainer:     libraries@haskell.org@@ -59,11 +59,11 @@     include-dirs: .      build-depends:-        base     >= 4.13.0 && < 4.21,+        base     >= 4.13.0 && < 4.23,         file-io  >= 0.1.4 && < 0.2,-        time     >= 1.8.0 && < 1.15,+        time     >= 1.8.0 && < 1.16,     if os(windows)-        build-depends: Win32 >= 2.13.3 && < 2.15+        build-depends: Win32 >= 2.14.1.0 && < 2.15     else         build-depends: unix >= 2.8.0 && < 2.9 
tests/Util.hs view
@@ -144,26 +144,54 @@   where cleanup dir' | keep      = return ()                      | otherwise = removePathForcibly dir' +diffAsc' :: (j -> k -> Ordering)+         -> (u -> v -> Bool)+         -> [(j, u)]+         -> [(k, v)]+         -> ([(j, u)], [(k, v)])+diffAsc' cmp eq = go id id+  where+    go a b [] [] = (a [], b [])+    go a b jus [] = go (a . (jus <>)) b [] []+    go a b [] kvs = go a (b . (kvs <>)) [] []+    go a b jus@((j, u) : jus') kvs@((k, v) : kvs') =+      case cmp j k of+        LT -> go (a . ((j, u) :)) b jus' kvs+        GT -> go a (b . ((k, v) :)) jus kvs'+        EQ | eq u v -> go a b jus' kvs'+           | otherwise -> go (a . ((j, u) :)) (b . ((k, v) :)) jus' kvs'++diffAsc :: (Ord k, Eq v) => [(k, v)] -> [(k, v)] -> ([(k, v)], [(k, v)])+diffAsc = diffAsc' compare (==)++-- Environment variables may be sensitive, so don't log their values.+scrubEnv :: (String, String) -> (String, String)+scrubEnv (k, v)+  -- Allowlist for nonsensitive variables.+  | k `elem` ["XDG_CONFIG_HOME"] = (k, v)+  | otherwise = (k, "<" <> show (length v) <> " chars>")+ isolateEnvironment :: IO a -> IO a isolateEnvironment = bracket getEnvs setEnvs . const   where+    -- Duplicate environment variables will cause problems for this code.+    -- https://github.com/haskell/cabal/issues/10718     getEnvs = List.sort . filter (\(k, _) -> k /= "") <$> getEnvironment     setEnvs target = do       current <- getEnvs-      updateEnvs current target+      let (deletions, insertions) = diffAsc current target+      updateEnvs deletions insertions       new <- getEnvs       when (target /= new) $ do-        -- Environment variables may be sensitive, so don't log them.-        throwIO (userError "isolateEnvironment.setEnvs failed")-    updateEnvs kvs1@((k1, v1) : kvs1') kvs2@((k2, v2) : kvs2') =-      case compare k1 k2 of-        LT -> unsetEnv k1 *> updateEnvs kvs1' kvs2-        EQ | v1 == v2 -> updateEnvs kvs1' kvs2'-           | otherwise -> setEnv k1 v2 *> updateEnvs kvs1' kvs2'-        GT -> setEnv k2 v2 *> updateEnvs kvs1 kvs2'-    updateEnvs [] [] = pure ()-    updateEnvs kvs1 [] = for_ kvs1 (unsetEnv . fst)-    updateEnvs [] kvs2 = for_ kvs2 (uncurry setEnv)+        let (missing, extraneous) = diffAsc target new+        throwIO (userError ("isolateEnvironment.setEnvs failed:" <>+                            " deletions=" <> show (scrubEnv <$> deletions) <>+                            " insertions=" <> show (scrubEnv <$> insertions) <>+                            " missing=" <> show (scrubEnv <$> missing) <>+                            " extraneous=" <> show (scrubEnv <$> extraneous)))+    updateEnvs deletions insertions = do+      for_ deletions (unsetEnv . fst)+      for_ insertions (uncurry setEnv)  isolateWorkingDirectory :: Bool -> OsPath -> IO a -> IO a isolateWorkingDirectory keep dir action = do