packages feed

cabal-gild 1.1.2.0 → 1.1.3.0

raw patch · 11 files changed

+153/−21 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ CabalGild.Exception.InvalidLeniency: InvalidLeniency :: String -> InvalidLeniency
+ CabalGild.Exception.InvalidLeniency: fromString :: String -> InvalidLeniency
+ CabalGild.Exception.InvalidLeniency: instance GHC.Classes.Eq CabalGild.Exception.InvalidLeniency.InvalidLeniency
+ CabalGild.Exception.InvalidLeniency: instance GHC.Exception.Type.Exception CabalGild.Exception.InvalidLeniency.InvalidLeniency
+ CabalGild.Exception.InvalidLeniency: instance GHC.Show.Show CabalGild.Exception.InvalidLeniency.InvalidLeniency
+ CabalGild.Exception.InvalidLeniency: newtype InvalidLeniency
+ CabalGild.Exception.SpecifiedCrlfWithFormatMode: SpecifiedCrlfWithFormatMode :: SpecifiedCrlfWithFormatMode
+ CabalGild.Exception.SpecifiedCrlfWithFormatMode: data SpecifiedCrlfWithFormatMode
+ CabalGild.Exception.SpecifiedCrlfWithFormatMode: instance GHC.Classes.Eq CabalGild.Exception.SpecifiedCrlfWithFormatMode.SpecifiedCrlfWithFormatMode
+ CabalGild.Exception.SpecifiedCrlfWithFormatMode: instance GHC.Exception.Type.Exception CabalGild.Exception.SpecifiedCrlfWithFormatMode.SpecifiedCrlfWithFormatMode
+ CabalGild.Exception.SpecifiedCrlfWithFormatMode: instance GHC.Show.Show CabalGild.Exception.SpecifiedCrlfWithFormatMode.SpecifiedCrlfWithFormatMode
+ CabalGild.Extra.ByteString: replace :: ByteString -> ByteString -> ByteString -> ByteString
+ CabalGild.Extra.ByteString: splitOn :: ByteString -> ByteString -> [ByteString]
+ CabalGild.Type.Config: [crlf] :: Config -> Optional Leniency
+ CabalGild.Type.Context: [crlf] :: Context -> Leniency
+ CabalGild.Type.Flag: CRLF :: String -> Flag
+ CabalGild.Type.Leniency: Lenient :: Leniency
+ CabalGild.Type.Leniency: Strict :: Leniency
+ CabalGild.Type.Leniency: data Leniency
+ CabalGild.Type.Leniency: fromString :: MonadThrow m => String -> m Leniency
+ CabalGild.Type.Leniency: instance GHC.Classes.Eq CabalGild.Type.Leniency.Leniency
+ CabalGild.Type.Leniency: instance GHC.Show.Show CabalGild.Type.Leniency.Leniency
- CabalGild.Type.Config: Config :: Optional Bool -> Optional Input -> Optional Mode -> Optional Output -> Optional FilePath -> Optional Bool -> Config
+ CabalGild.Type.Config: Config :: Optional Leniency -> Optional Bool -> Optional Input -> Optional Mode -> Optional Output -> Optional FilePath -> Optional Bool -> Config
- CabalGild.Type.Context: Context :: Input -> Mode -> Output -> FilePath -> Context
+ CabalGild.Type.Context: Context :: Leniency -> Input -> Mode -> Output -> FilePath -> Context

Files

README.md view
@@ -130,6 +130,15 @@  - `--version`: Prints the version number to STDOUT then exits successfully. +- `--crlf=LENIENCY`: Sets the CRLF handling mode, which must be either+  `lenient` (the default) or `strict`. When checking if the input is formatted,+  setting this to `lenient` will treat CRLF line endings the same as LF.+  Setting this to `strict` will require the input to be byte-for-byte identical+  to the expected output. (Note that Gild will never produce CRLF line endings+  when formatting.)++  It is an error to provide a value for this option unless the mode is `check`.+ - `--input=FILE`: Uses `FILE` as the input. If this is `-` (which is the   default), then the input will be read from STDIN. 
cabal-gild.cabal view
@@ -11,7 +11,7 @@ maintainer: Taylor Fausak name: cabal-gild synopsis: Formats package descriptions.-version: 1.1.2.0+version: 1.1.3.0  source-repository head   type: git@@ -86,13 +86,16 @@     CabalGild.Class.MonadWalk     CabalGild.Class.MonadWrite     CabalGild.Exception.CheckFailure+    CabalGild.Exception.InvalidLeniency     CabalGild.Exception.InvalidMode     CabalGild.Exception.InvalidOption     CabalGild.Exception.ParseError+    CabalGild.Exception.SpecifiedCrlfWithFormatMode     CabalGild.Exception.SpecifiedOutputWithCheckMode     CabalGild.Exception.SpecifiedStdinWithFileInput     CabalGild.Exception.UnexpectedArgument     CabalGild.Exception.UnknownOption+    CabalGild.Extra.ByteString     CabalGild.Extra.Either     CabalGild.Extra.Field     CabalGild.Extra.FieldLine@@ -115,6 +118,7 @@     CabalGild.Type.Input     CabalGild.Type.Language     CabalGild.Type.LegacyExeDependency+    CabalGild.Type.Leniency     CabalGild.Type.Line     CabalGild.Type.List     CabalGild.Type.Mode
+ source/library/CabalGild/Exception/InvalidLeniency.hs view
@@ -0,0 +1,16 @@+module CabalGild.Exception.InvalidLeniency where++import qualified Control.Monad.Catch as Exception++-- | This exception is thrown when the given+-- 'CabalGild.Type.Leniency.Leniency' is invalid.+newtype InvalidLeniency+  = InvalidLeniency String+  deriving (Eq, Show)++instance Exception.Exception InvalidLeniency where+  displayException (InvalidLeniency s) = "invalid leniency: " <> s++-- | Constructs an 'InvalidLeniency' from the given 'String'.+fromString :: String -> InvalidLeniency+fromString = InvalidLeniency
+ source/library/CabalGild/Exception/SpecifiedCrlfWithFormatMode.hs view
@@ -0,0 +1,13 @@+module CabalGild.Exception.SpecifiedCrlfWithFormatMode where++import qualified Control.Monad.Catch as Exception++-- | This exception is thrown when the user specifies the CRLF leniency while+-- using the format mode. In other words, when @--mode=format@ and+-- @--crlf=anything@.+data SpecifiedCrlfWithFormatMode+  = SpecifiedCrlfWithFormatMode+  deriving (Eq, Show)++instance Exception.Exception SpecifiedCrlfWithFormatMode where+  displayException = const "cannot use --crlf when --mode is format"
+ source/library/CabalGild/Extra/ByteString.hs view
@@ -0,0 +1,32 @@+module CabalGild.Extra.ByteString where++import qualified Data.ByteString as ByteString++-- | Calling @replace needle replacement haystack@ will replace every+-- non-overlapping occurrence of @needle@ in @haystack@ with @replacement@.+--+-- <https://github.com/haskell/bytestring/issues/307>+replace ::+  ByteString.ByteString ->+  ByteString.ByteString ->+  ByteString.ByteString ->+  ByteString.ByteString+replace needle replacement = ByteString.intercalate replacement . splitOn needle++-- | Calling @splitOn needle haystack@ will split @haystack@ into a list of+-- substrings using @needle@ as the delimiter.+--+-- <https://github.com/haskell/bytestring/issues/100>+splitOn ::+  ByteString.ByteString ->+  ByteString.ByteString ->+  [ByteString.ByteString]+splitOn needle =+  let split = ByteString.breakSubstring needle+      go haystack =+        let (before, after) = split haystack+         in before+              : if ByteString.null after+                then []+                else go (ByteString.drop (ByteString.length needle) after)+   in go
source/library/CabalGild/Main.hs view
@@ -16,15 +16,16 @@ import qualified CabalGild.Class.MonadWrite as MonadWrite import qualified CabalGild.Exception.CheckFailure as CheckFailure import qualified CabalGild.Exception.ParseError as ParseError+import qualified CabalGild.Extra.ByteString as ByteString import qualified CabalGild.Type.Config as Config import qualified CabalGild.Type.Context as Context import qualified CabalGild.Type.Flag as Flag import qualified CabalGild.Type.Input as Input+import qualified CabalGild.Type.Leniency as Leniency import qualified CabalGild.Type.Mode as Mode import qualified Control.Monad as Monad import qualified Control.Monad.Catch as Exception import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Char8 as Latin1 import qualified Distribution.Fields as Fields import qualified System.Environment as Environment import qualified System.Exit as Exit@@ -89,17 +90,13 @@    case Context.mode context of     Mode.Check -> do-      -- The input might have CRLF ("\r\n", 0x0d 0x0a) line endings, but the-      -- output will always have LF line endings. For the purposes of the check-      -- command, we'll consider the input formatted if it only differs from-      -- the output in line endings.-      let outputLines = Latin1.lines output-          stripCR x = case ByteString.unsnoc x of-            Just (y, 0x0d) -> y-            _ -> x-          inputLines = stripCR <$> Latin1.lines input-      Monad.when (outputLines /= inputLines) $-        Exception.throwM CheckFailure.CheckFailure+      let formatted = case Context.crlf context of+            Leniency.Lenient ->+              let lf = ByteString.singleton 0x0a+                  crlf = ByteString.cons 0x0d lf+               in output == ByteString.replace crlf lf input+            Leniency.Strict -> output == input+      Monad.unless formatted $ Exception.throwM CheckFailure.CheckFailure     Mode.Format -> do       let target = Context.output context       MonadWrite.write target output
source/library/CabalGild/Type/Config.hs view
@@ -3,6 +3,7 @@  import qualified CabalGild.Type.Flag as Flag import qualified CabalGild.Type.Input as Input+import qualified CabalGild.Type.Leniency as Leniency import qualified CabalGild.Type.Mode as Mode import qualified CabalGild.Type.Optional as Optional import qualified CabalGild.Type.Output as Output@@ -12,7 +13,8 @@ -- | This data type represents the configuration for the command line utility. -- Each field typically corresponds to a flag. data Config = Config-  { help :: Optional.Optional Bool,+  { crlf :: Optional.Optional Leniency.Leniency,+    help :: Optional.Optional Bool,     input :: Optional.Optional Input.Input,     mode :: Optional.Optional Mode.Mode,     output :: Optional.Optional Output.Output,@@ -25,7 +27,8 @@ initial :: Config initial =   Config-    { help = Optional.Default,+    { crlf = Optional.Default,+      help = Optional.Default,       input = Optional.Default,       mode = Optional.Default,       output = Optional.Default,@@ -36,6 +39,9 @@ -- | Applies a flag to the config, returning the new config. applyFlag :: (Exception.MonadThrow m) => Config -> Flag.Flag -> m Config applyFlag config flag = case flag of+  Flag.CRLF s -> do+    l <- Leniency.fromString s+    pure config {crlf = Optional.Specific l}   Flag.Help b -> pure config {help = Optional.Specific b}   Flag.Input s -> pure config {input = Optional.Specific $ Input.fromString s}   Flag.IO s ->
source/library/CabalGild/Type/Context.hs view
@@ -1,11 +1,13 @@ module CabalGild.Type.Context where  import qualified CabalGild.Class.MonadLog as MonadLog+import qualified CabalGild.Exception.SpecifiedCrlfWithFormatMode as SpecifiedCrlfWithFormatMode import qualified CabalGild.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode import qualified CabalGild.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput import qualified CabalGild.Type.Config as Config import qualified CabalGild.Type.Flag as Flag import qualified CabalGild.Type.Input as Input+import qualified CabalGild.Type.Leniency as Leniency import qualified CabalGild.Type.Mode as Mode import qualified CabalGild.Type.Optional as Optional import qualified CabalGild.Type.Output as Output@@ -21,7 +23,8 @@ -- | Represents the context necessary to run the program. This is essentially a -- simplified 'Config.Config'. data Context = Context-  { input :: Input.Input,+  { crlf :: Leniency.Leniency,+    input :: Input.Input,     mode :: Mode.Mode,     output :: Output.Output,     stdin :: FilePath@@ -64,9 +67,16 @@       Exception.throwM SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode     _ -> pure () +  case Config.crlf config of+    Optional.Specific _+      | Config.mode config /= Optional.Specific Mode.Check ->+          Exception.throwM SpecifiedCrlfWithFormatMode.SpecifiedCrlfWithFormatMode+    _ -> pure ()+   pure     Context-      { input = Optional.withDefault Input.Stdin $ Config.input config,+      { crlf = Optional.withDefault Leniency.Lenient $ Config.crlf config,+        input = Optional.withDefault Input.Stdin $ Config.input config,         mode = Optional.withDefault Mode.Format $ Config.mode config,         output = Optional.withDefault Output.Stdout $ Config.output config,         stdin = Optional.withDefault "." $ Config.stdin config
source/library/CabalGild/Type/Flag.hs view
@@ -11,7 +11,8 @@ -- the flags are typically not parsed. These just handle the structure of -- command line options. data Flag-  = Help Bool+  = CRLF String+  | Help Bool   | Input String   | IO String   | Mode String@@ -43,6 +44,11 @@       ["no-version"]       (GetOpt.NoArg $ Version False)       "",+    GetOpt.Option+      []+      ["crlf"]+      (GetOpt.ReqArg CRLF "LENIENCY")+      "Sets the CRLF handling mode. Must be either 'lenient' or 'strict'.\nDefault: 'lenient'",     GetOpt.Option       ['i']       ["input"]
+ source/library/CabalGild/Type/Leniency.hs view
@@ -0,0 +1,18 @@+module CabalGild.Type.Leniency where++import qualified CabalGild.Exception.InvalidLeniency as InvalidLeniency+import qualified Control.Monad.Catch as Exception++-- | Represents the leniency of a setting. In other words, should something be+-- lenient\/permissive or strict\/pedantic?+data Leniency+  = Lenient+  | Strict+  deriving (Eq, Show)++-- | Attempts to parse a string as a 'Leniency'.+fromString :: (Exception.MonadThrow m) => String -> m Leniency+fromString s = case s of+  "lenient" -> pure Lenient+  "strict" -> pure Strict+  _ -> Exception.throwM $ InvalidLeniency.fromString s
source/test-suite/Main.hs view
@@ -5,6 +5,7 @@ import qualified CabalGild.Class.MonadWalk as MonadWalk import qualified CabalGild.Class.MonadWrite as MonadWrite import qualified CabalGild.Exception.CheckFailure as CheckFailure+import qualified CabalGild.Exception.SpecifiedCrlfWithFormatMode as SpecifiedCrlfWithFormatMode import qualified CabalGild.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode import qualified CabalGild.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput import qualified CabalGild.Extra.String as String@@ -70,7 +71,7 @@     let (a, s, w) =           runTest             (Gild.mainWith ["--mode", "check"])-            (Map.singleton Input.Stdin (String.toUtf8 ""), Map.empty)+            (Map.singleton Input.Stdin (String.toUtf8 "pass: yes\n"), Map.empty)             Map.empty     a `Hspec.shouldBe` Right ()     w `Hspec.shouldBe` []@@ -80,13 +81,13 @@     let (a, s, w) =           runTest             (Gild.mainWith ["--mode", "check"])-            (Map.singleton Input.Stdin (String.toUtf8 "fail:yes"), Map.empty)+            (Map.singleton Input.Stdin (String.toUtf8 "pass: no"), Map.empty)             Map.empty     a `Hspec.shouldBe` Left (Problem $ Exception.toException CheckFailure.CheckFailure)     w `Hspec.shouldBe` []     s `Hspec.shouldBe` Map.empty -  Hspec.it "succeeds when checking CRLF input" $ do+  Hspec.it "succeeds when checking CRLF input leniently" $ do     let (a, s, w) =           runTest             (Gild.mainWith ["--mode", "check"])@@ -96,6 +97,16 @@     w `Hspec.shouldBe` []     s `Hspec.shouldBe` Map.empty +  Hspec.it "fails when checking CRLF input strictly" $ do+    let (a, s, w) =+          runTest+            (Gild.mainWith ["--crlf", "strict", "--mode", "check"])+            (Map.singleton Input.Stdin (String.toUtf8 "pass: no\r\n"), Map.empty)+            Map.empty+    a `Hspec.shouldBe` Left (Problem $ Exception.toException CheckFailure.CheckFailure)+    w `Hspec.shouldBe` []+    s `Hspec.shouldBe` Map.empty+   Hspec.it "fails when --stdin is given with an input file" $ do     let (a, s, w) =           runTest@@ -125,6 +136,16 @@     a `Hspec.shouldBe` Right ()     w `Hspec.shouldBe` []     s `Hspec.shouldSatisfy` Map.member (Output.File "io.cabal")++  Hspec.it "fails when --crlf is given with format mode" $ do+    let (a, s, w) =+          runTest+            (Gild.mainWith ["--crlf", "strict"])+            (Map.empty, Map.empty)+            Map.empty+    a `Hspec.shouldBe` Left (Problem $ Exception.toException SpecifiedCrlfWithFormatMode.SpecifiedCrlfWithFormatMode)+    w `Hspec.shouldBe` []+    s `Hspec.shouldBe` Map.empty    Hspec.it "succeeds with empty input" $ do     expectGilded