shelly 1.8.0 → 1.8.1
raw patch · 4 files changed
+62/−13 lines, 4 filesdep +unixdep ~directoryPVP ok
version bump matches the API change (PVP)
Dependencies added: unix
Dependency ranges changed: directory
API changes (from Hackage documentation)
Files
- ChangeLog.md +4/−0
- shelly.cabal +6/−4
- src/Shelly.hs +16/−9
- src/Shelly/Directory.hs +36/−0
ChangeLog.md view
@@ -1,3 +1,7 @@+# 1.8.1++There is a new function `cp_should_follow_symlinks` to specify whether a copy should follow symlinks.+ # 1.8.0 * `cp_r` now uses upper case R: `cp -R`
shelly.cabal view
@@ -1,6 +1,6 @@ Name: shelly -Version: 1.8.0+Version: 1.8.1 Synopsis: shell-like (systems) programming in Haskell Description: Shelly provides convenient systems programming in Haskell,@@ -44,16 +44,17 @@ Library Exposed-modules: Shelly, Shelly.Lifted, Shelly.Pipe, Shelly.Unix- other-modules: Shelly.Base, Shelly.Find+ other-modules: Shelly.Base, Shelly.Find, Shelly.Directory hs-source-dirs: src Build-depends: containers >= 0.4.2.0, time >= 1.3 && < 1.9,- directory >= 1.1.0.0 && < 1.4.0.0,+ directory >= 1.3.0.0 && < 1.4.0.0, mtl >= 2, process >= 1.0, unix-compat < 0.6,+ unix, system-filepath >= 0.4.7 && < 0.5, system-fileio < 0.4, monad-control >= 0.3.2 && < 1.1,@@ -125,9 +126,10 @@ async, bytestring >= 0.10, containers >= 0.5.0.0,- directory >= 1.1.0.0 && < 1.4.0.0,+ directory >= 1.3.0.0 && < 1.4.0.0, process >= 1.1.0, unix-compat < 0.6,+ unix, system-filepath >= 0.4.7 && < 0.5, system-fileio < 0.4, time >= 1.3 && < 1.9,
src/Shelly.hs view
@@ -94,6 +94,7 @@ ) where import Shelly.Base+import Shelly.Directory import Shelly.Find import Control.Monad ( when, unless, void, forM, filterM, liftM2 ) import Control.Monad.Trans ( MonadIO )@@ -141,7 +142,7 @@ import Filesystem hiding (canonicalizePath) import qualified Filesystem.Path.CurrentOS as FP -import System.Directory ( setPermissions, getPermissions, Permissions(..), getTemporaryDirectory )+import System.Directory ( setPermissions, getPermissions, Permissions(..), getTemporaryDirectory, pathIsSymbolicLink ) import Data.Char (isDigit) import Data.Tree(Tree(..))@@ -1398,8 +1399,8 @@ cp_r from' to' = do from <- absPath from' fromIsDir <- (test_d from)- if not fromIsDir then cp from' to' else do- trace $ "cp -R " <> toTextIgnore from <> " " <> toTextIgnore to'+ if not fromIsDir then cp_should_follow_symlinks False from' to' else do+ trace $ "cp_r " <> toTextIgnore from <> " " <> toTextIgnore to' to <- absPath to' toIsDir <- test_d to @@ -1415,19 +1416,25 @@ -- | Copy a file. The second path could be a directory, in which case the -- original file name is used, in that directory. cp :: FilePath -> FilePath -> Sh ()-cp from' to' = do+cp = cp_should_follow_symlinks True++cp_should_follow_symlinks :: Bool -> FilePath -> FilePath -> Sh ()+cp_should_follow_symlinks shouldFollowSymlinks from' to' = do from <- absPath from' to <- absPath to' trace $ "cp " <> toTextIgnore from <> " " <> toTextIgnore to to_dir <- test_d to let to_loc = if to_dir then to FP.</> filename from else to- liftIO $ copyFile from to_loc `catchany` (\e -> throwIO $- ReThrownException e (extraMsg to_loc from)- )+ if shouldFollowSymlinks then copyNormal from to_loc else do+ isSymlink <- liftIO $ pathIsSymbolicLink (encodeString from)+ if not isSymlink then copyNormal from to_loc else do+ target <- liftIO $ getSymbolicLinkTarget (encodeString from)+ liftIO $ createFileLink target (encodeString to_loc) where extraMsg t f = "during copy from: " ++ encodeString f ++ " to: " ++ encodeString t--+ copyNormal from to = liftIO $ copyFile from to `catchany` (\e -> throwIO $+ ReThrownException e (extraMsg to from)+ ) -- | Create a temporary directory and pass it as a parameter to a Sh -- computation. The directory is nuked afterwards.
+ src/Shelly/Directory.hs view
@@ -0,0 +1,36 @@+{-# OPTIONS -Wall #-}+module Shelly.Directory where++import System.IO.Error (modifyIOError, ioeSetLocation, ioeGetLocation)+import qualified Filesystem.Path.CurrentOS as FP++#ifdef mingw32_HOST_OS+import qualified System.Win32 as Win32+#else+import qualified System.Posix as Posix+#endif++createFileLink :: String -> String -> IO ()+createFileLink target link =+ (`ioeAddLocation` "createFileLink") `modifyIOError` do+#ifdef mingw32_HOST_OS+ Win32.createSymbolicLink False target link+#else+ Posix.createSymbolicLink target link+#endif++getSymbolicLinkTarget :: String -> IO String+getSymbolicLinkTarget path =+ (`ioeAddLocation` "getSymbolicLinkTarget") `modifyIOError` do+#ifdef mingw32_HOST_OS+ Win32.readSymbolicLink path+#else+ Posix.readSymbolicLink path+#endif++ioeAddLocation :: IOError -> String -> IOError+ioeAddLocation e loc = do+ ioeSetLocation e newLoc+ where+ newLoc = loc ++ if Prelude.null oldLoc then "" else ":" ++ oldLoc+ oldLoc = ioeGetLocation e