shelly 1.6.9 → 1.7.0
raw patch · 3 files changed
+46/−7 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- shelly.cabal +1/−1
- src/Shelly.hs +21/−3
- test/src/SshSpec.hs +24/−3
shelly.cabal view
@@ -1,6 +1,6 @@ Name: shelly -Version: 1.6.9+Version: 1.7.0 Synopsis: shell-like (systems) programming in Haskell Description: Shelly provides convenient systems programming in Haskell,
src/Shelly.hs view
@@ -1043,6 +1043,19 @@ quote t | T.any isSpace t = surround '\'' t quote t | otherwise = t +-- quote one argument+quoteOne :: Text -> Text+quoteOne t =+ surround '\'' $ T.replace "'" "'\\''" t+++-- returns a string that can be executed by a shell.+-- NOTE: all parts are treated literally, which means that+-- things like variable expansion will not be available.+quoteCommand :: FilePath -> [Text] -> Text+quoteCommand exe args =+ T.intercalate " " $ map quoteOne (toTextIgnore exe : args)+ surround :: Char -> Text -> Text surround c t = T.cons c $ T.snoc t c @@ -1067,7 +1080,13 @@ -- -- This interface is crude, but it works for now. ----- Please note this sets 'escaping' to False: the commands will not be shell escaped.+-- Please note this sets 'escaping' to False, and the remote commands are+-- quoted with single quotes, in a way such that the remote commands will see+-- the literal values you passed, this means that no variable expansion and+-- alike will done on either the local shell or the remote shell, and that+-- if there are a single or double quotes in your arguments, they need not+-- to be quoted manually.+-- -- Internally the list of commands are combined with the string @&&@ before given to ssh. sshPairs :: Text -> [(FilePath, [Text])] -> Sh Text sshPairs _ [] = return ""@@ -1098,9 +1117,8 @@ sshCommandText :: [(FilePath, [Text])] -> SshMode -> Text sshCommandText actions mode =- surround '"' (foldl1 joiner (map toSSH actions))+ quoteOne (foldl1 joiner (map (uncurry quoteCommand) actions)) where- toSSH (exe,args) = show_command exe args joiner memo next = case mode of SeqSsh -> memo <> " && " <> next ParSsh -> memo <> " & " <> next
test/src/SshSpec.hs view
@@ -1,18 +1,39 @@+{-# LANGUAGE OverloadedStrings #-} module SshSpec ( sshSpec ) where import TestInit+import qualified Data.Text as T sshSpec :: Spec sshSpec = do+ let q = "'" -- a single quote+ let qq = "'\\''" -- quote of a single quote+ let qqq = T.concat [qq, "\\", qq, qq] -- quote of qq describe "sshCommandText" $ do it "simple command" $ do let res = sshCommandText [("wibble", [])] SeqSsh- res @?= "\"wibble\""+ res @?= T.concat [q, qq, "wibble", qq, q] it "space command" $ do let res = sshCommandText [("to", ["outer space"])] SeqSsh- res @?= "\"to 'outer space'\""+ res @?= T.concat [q, qq, "to", qq, " ", qq, "outer space", qq ,q] it "multiple space commands" $ do let res = sshCommandText [("to", ["outer space"]), ("and", ["back again"])] SeqSsh- res @?= "\"to 'outer space' && and 'back again'\""+ res @?= T.concat+ [ q, qq, "to", qq, " ", qq, "outer space", qq+ , " && "+ , qq, "and", qq, " ", qq, "back again", qq, q+ ]++ it "commands with quotes and spaces" $ do+ let res = sshCommandText [ ("echo", ["Godfater's brother, Tom says: \"huh??\""])+ , ("foo", ["--dir", "Tom's father/"])] SeqSsh+ res @?= T.concat+ [ q, qq, "echo", qq, " "+ , qq, "Godfater", qqq, "s brother, Tom says: \"huh??\"", qq+ , " && "+ , qq, "foo", qq, " "+ , qq, "--dir", qq, " "+ , qq, "Tom", qqq, "s father/", qq, q+ ]