shelly 1.10.0.1 → 1.11.0
raw patch · 6 files changed
+48/−37 lines, 6 files
Files
- ChangeLog.md +9/−0
- shelly.cabal +2/−1
- src/Shelly.hs +26/−36
- test/data/hello.sh +3/−0
- test/src/FindSpec.hs +2/−0
- test/src/RunSpec.hs +6/−0
ChangeLog.md view
@@ -1,3 +1,12 @@+# 1.11.0++Andreas Abel, 2023-01-24+* Restore running of local scripts, e.g. `cmd "./foo.sh"`:+ Issue [#107](https://github.com/gregwebs/Shelly.hs/issues/107)+ fixed by Alfredo di Napoli in PR+ [#216](https://github.com/gregwebs/Shelly.hs/pull/216).+* Builds with GHC 8.0 - 9.4.+ # 1.10.0.1 Andreas Abel, 2023-01-24
shelly.cabal view
@@ -1,6 +1,6 @@ Name: shelly -Version: 1.10.0.1+Version: 1.11.0 Synopsis: shell-like (systems) programming in Haskell Description: Shelly provides convenient systems programming in Haskell,@@ -48,6 +48,7 @@ test/data/zshrc test/data/nonascii.txt test/data/symlinked_dir/hoge_file+ test/data/hello.sh test/testall README.md ChangeLog.md
src/Shelly.hs view
@@ -106,7 +106,7 @@ import Control.Concurrent import Control.Concurrent.Async (async, wait, Async) import Control.Exception-import Control.Monad ( when, unless, void, forM, filterM, liftM2 )+import Control.Monad ( when, unless, void, liftM2 ) import Control.Monad.Trans ( MonadIO ) import Control.Monad.Reader (ask) @@ -122,14 +122,11 @@ import Data.Semigroup ( (<>) ) #endif import Data.Sequence ( Seq, (|>) )-import Data.Set ( Set ) import Data.Time.Clock ( getCurrentTime, diffUTCTime ) import Data.Tree ( Tree(..) ) import Data.Typeable import qualified Data.ByteString as BS-import qualified Data.List as List-import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Text.IO as TIO import qualified Data.Text.Encoding as TE@@ -137,7 +134,7 @@ import System.Directory ( setPermissions, getPermissions, Permissions(..), getTemporaryDirectory, pathIsSymbolicLink- , copyFile, removeFile, doesFileExist, doesDirectoryExist, listDirectory+ , copyFile, removeFile, doesFileExist, doesDirectoryExist , renameFile, renameDirectory, removeDirectoryRecursive, createDirectoryIfMissing , getCurrentDirectory )@@ -605,15 +602,33 @@ whichFull fp = do (trace . mappend "which " . toTextIgnore) fp >> whichUntraced where- whichUntraced | isAbsolute fp = checkFile- | dotSlash splitOnDirs = checkFile- | length splitOnDirs > 0 = lookupPath >>= leftPathError- | otherwise = lookupCache >>= leftPathError+ whichUntraced | isAbsolute fp = checkFile+ | startsWithDot splitOnDirs = checkFile+ | otherwise = lookupPath >>= leftPathError splitOnDirs = splitDirectories fp- dotSlash ("./":_) = True- dotSlash _ = False + -- 'startsWithDot' receives as input the result of 'splitDirectories',+ -- which will include the dot (\".\") as its first element only if this+ -- is a path of the form \"./foo/bar/baz.sh\". Check for example:+ --+ -- > import System.FilePath as FP+ -- > FP.splitDirectories "./test/data/hello.sh"+ -- [".","test","data","hello.sh"]+ -- > FP.splitDirectories ".hello.sh"+ -- [".hello.sh"]+ -- > FP.splitDirectories ".test/hello.sh"+ -- [".test","hello.sh"]+ -- > FP.splitDirectories ".foo"+ -- [".foo"]+ --+ -- Note that earlier versions of Shelly used+ -- \"system-filepath\" which also has a 'splitDirectories'+ -- function, but it returns \"./\" as its first argument,+ -- so we pattern match on both for backward-compatibility.+ startsWithDot (".":_) = True+ startsWithDot _ = False+ checkFile :: Sh (Either String FilePath) checkFile = do exists <- liftIO $ doesFileExist fp@@ -637,32 +652,7 @@ res <- liftIO $ isExecutable fullFp return $ if res then Just fullFp else Nothing - lookupCache :: Sh (Maybe FilePath)- lookupCache = do- pathExecutables <- cachedPathExecutables- return $ fmap (flip (</>) fp . fst) $- List.find (Set.member fp . snd) pathExecutables-- pathDirs = mapM absPath =<< ((map T.unpack . filter (not . T.null) . T.split (== searchPathSeparator)) `fmap` get_env_text "PATH")-- cachedPathExecutables :: Sh [(FilePath, Set FilePath)]- cachedPathExecutables = do- mPathExecutables <- gets sPathExecutables- case mPathExecutables of- Just pExecutables -> return pExecutables- Nothing -> do- dirs <- pathDirs- executables <- forM dirs (\dir -> do- files <- (liftIO . listDirectory) dir `catch_sh` (\(_ :: IOError) -> return [])- exes <- fmap (map snd) $ liftIO $ filterM (isExecutable . fst) $- map (\f -> (f, takeFileName f)) files- return $ Set.fromList exes- )- let cachedExecutables = zip dirs executables- modify $ \x -> x { sPathExecutables = Just cachedExecutables }- return $ cachedExecutables- -- | A monadic findMap, taken from MissingM package findMapM :: Monad m => (a -> m (Maybe b)) -> [a] -> m (Maybe b)
+ test/data/hello.sh view
@@ -0,0 +1,3 @@+#!/usr/bin/env bash++echo -n "Hello!"
test/src/FindSpec.hs view
@@ -115,6 +115,7 @@ [ "dir" , "dir/symlinked_dir" , "dir/symlinked_dir/hoge_file"+ , "hello.sh" , "nonascii.txt" , "symlinked_dir" , "symlinked_dir/hoge_file"@@ -128,6 +129,7 @@ sort res @?= [ "dir" , "dir/symlinked_dir"+ , "hello.sh" , "nonascii.txt" , "symlinked_dir" , "symlinked_dir/hoge_file"
test/src/RunSpec.hs view
@@ -28,6 +28,12 @@ if isWindows then res @?= "Selbstverst\228ndlich \252berraschend\r\n" else res @?= "Selbstverst\228ndlich \252berraschend\n"+ unless isWindows $ do+ it "script at $PWD" $ do+ res <- shelly $ do+ run_ "chmod" ["+x", "test/data/hello.sh"]+ run "./test/data/hello.sh" []+ res @?= "Hello!\n" -- Bash-related commands describe "bash" $ do