packages feed

cabal-add 0.2 → 0.2.1

raw patch · 7 files changed

+1908/−1778 lines, 7 filesdep +cabal-installdep +file-iodep +temporary-ospathdep −cabal-install-parsersdep −string-qqdep −temporarydep ~Cabaldep ~Cabal-syntaxdep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: cabal-install, file-io, temporary-ospath

Dependencies removed: cabal-install-parsers, string-qq, temporary

Dependency ranges changed: Cabal, Cabal-syntax, bytestring, directory, filepath, process

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,8 @@+## 0.2.1++* Migrate the executable from `cabal-install-parsers` to `cabal-install` proper.+* Do not attempt to rename entities inside comments.+ ## 0.2  * Allow add not only dependencies, but also modules.
app/Main.hs view
@@ -1,33 +1,50 @@ {-# LANGUAGE ApplicativeDo #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE RecordWildCards #-}+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}  -- | -- Copyright:   (c) 2023 Bodigrim -- License:     BSD-3-Clause module Main (main) where -import Cabal.Project (parseProject, prjPackages, resolveProject) import Control.Exception (throwIO) import Control.Monad (filterM)+import Control.Monad.IO.Class (liftIO) import Data.Bifunctor (bimap) import Data.ByteString (ByteString) import Data.ByteString.Char8 qualified as B import Data.Either (partitionEithers) import Data.List qualified as L import Data.List.NonEmpty (NonEmpty (..))-import Data.Maybe (catMaybes, isJust)+import Data.Maybe (catMaybes, isJust, mapMaybe) import Distribution.CabalSpecVersion (CabalSpecVersion) import Distribution.Client.Add+import Distribution.Client.DistDirLayout (+  defaultDistDirLayout,+  distProjectRootDirectory,+ )+import Distribution.Client.HttpUtils (configureTransport)+import Distribution.Client.ProjectConfig (+  ProjectPackageLocation (..),+  findProjectPackages,+  findProjectRoot,+  readProjectConfig,+ )+import Distribution.Client.RebuildMonad (runRebuild) import Distribution.PackageDescription (   ComponentName,   GenericPackageDescription,+  ignoreConditions,   packageDescription,   specVersion,  ) import Distribution.PackageDescription.Quirks (patchQuirks)+import Distribution.Verbosity qualified as Verbosity import Options.Applicative (   Parser,   execParser,@@ -46,8 +63,12 @@ import System.Directory (doesFileExist, listDirectory) import System.Environment (getArgs, lookupEnv, withArgs) import System.Exit (die)-import System.FilePath (takeDirectory, (</>))+import System.FilePath (splitFileName, (</>)) +#if MIN_VERSION_Cabal(3,17,0)+import Distribution.Client.ProjectConfig (ProjectFileParser(..))+#endif+ data RawConfig = RawConfig   { rcnfMProjectFile :: !(Maybe FilePath)   , rcnfArgs :: !(NonEmpty String)@@ -94,14 +115,49 @@  extractCabalFilesFromProject :: FilePath -> IO [FilePath] extractCabalFilesFromProject projectFn = do-  project <- B.readFile projectFn-  parsed <- case parseProject projectFn project of-    Left exc -> throwIO exc-    Right p -> pure p-  resolved <- resolveProject projectFn parsed-  case resolved of+  let (projectDir, projectFile) = splitFileName projectFn+  mProjectRoot <- findProjectRoot silent (Just projectDir) (Just projectFile)+  case mProjectRoot of     Left exc -> throwIO exc-    Right prj -> pure $ map (takeDirectory projectFn </>) $ prjPackages prj+    Right projectRoot -> do+      let dirLayout = defaultDistDirLayout projectRoot Nothing Nothing+          rootDirectory = distProjectRootDirectory dirLayout+      runRebuild rootDirectory $ do+        httpTransport <- liftIO $ configureTransport silent [] Nothing+        skeleton <- readProjectConfigSilently httpTransport mempty mempty dirLayout+        let projectConfig = fromSkeleton skeleton+        packages <- findProjectPackages dirLayout projectConfig+        pure $ map (rootDirectory </>) $ mapMaybe extractCabalFileFromProjectPackageLocation packages++#if MIN_VERSION_Cabal(3,17,0)+silent :: Verbosity.Verbosity+silent = Verbosity.Verbosity { verbosityFlags = Verbosity.silent, verbosityHandles = Verbosity.defaultVerbosityHandles }+#else+silent :: Verbosity.Verbosity+silent = Verbosity.silent+#endif++#if MIN_VERSION_Cabal(3,17,0)+readProjectConfigSilently :: _+readProjectConfigSilently = readProjectConfig silent ParsecParser+#else+readProjectConfigSilently :: _+readProjectConfigSilently = readProjectConfig silent+#endif++#if MIN_VERSION_Cabal(3,17,0)+fromSkeleton :: _+fromSkeleton = snd . ignoreConditions+#else+fromSkeleton :: _+fromSkeleton = fst . ignoreConditions+#endif++extractCabalFileFromProjectPackageLocation :: ProjectPackageLocation -> Maybe FilePath+extractCabalFileFromProjectPackageLocation = \case+  ProjectPackageLocalCabalFile fn -> Just fn+  ProjectPackageLocalDirectory _dn fn -> Just fn+  _ -> Nothing  resolveCabalFiles :: Maybe FilePath -> IO [FilePath] resolveCabalFiles = \case
cabal-add.cabal view
@@ -1,12 +1,13 @@ cabal-version:   3.0 name:            cabal-add-version:         0.2+version:         0.2.1 license:         BSD-3-Clause license-file:    LICENSE maintainer:      andrew.lelechenko@gmail.com author:          Bodigrim tested-with:-    ghc ==9.12.2 ghc ==9.10.2 ghc ==9.8.4 ghc ==9.6.7 ghc ==9.4.8+    ghc ==9.14.1 ghc ==9.12.2 ghc ==9.10.3 ghc ==9.8.4 ghc ==9.6.7+    ghc ==9.4.8  synopsis:        Extend Cabal build-depends from the command line description:@@ -37,8 +38,8 @@     build-depends:         base <5,         bytestring <0.13,-        Cabal >=3.8 && <3.15,-        Cabal-syntax >=3.8 && <3.15,+        Cabal >=3.8 && <3.19,+        Cabal-syntax >=3.8 && <3.19,         containers <0.9,         mtl <2.4 @@ -51,12 +52,12 @@         base <5,         bytestring <0.13,         cabal-add,-        cabal-install-parsers >=0.4.1 && <0.7,+        Cabal,+        cabal-install >=3.12 && <3.19,         Cabal-syntax,         directory <1.4,         filepath <1.6,-        optparse-applicative >=0.16 && <0.20,-        process <1.7+        optparse-applicative >=0.16 && <0.20  test-suite cabal-add-tests     type:               exitcode-stdio-1.0@@ -64,21 +65,25 @@     build-tool-depends: cabal-add:cabal-add     hs-source-dirs:     tests     default-language:   GHC2021+    other-extensions:   MultilineStrings     ghc-options:        -Wall     build-depends:         base <5,+        bytestring >=0.11.2,         Diff >=0.4,         directory,+        file-io,+        filepath,         process,-        string-qq,         tasty,-        temporary+        temporary-ospath <1.4  test-suite cabal-add-unit-tests     type:             exitcode-stdio-1.0     main-is:          UnitTests.hs     hs-source-dirs:   tests/     default-language: GHC2021+    other-extensions: MultilineStrings     ghc-options:      -Wall     build-depends:         base <5,@@ -86,8 +91,4 @@         Cabal,         cabal-add,         Diff >=0.4,-        directory,-        process,-        string-qq,-        tasty,-        temporary+        tasty
src/Distribution/Client/Add.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}@@ -69,6 +70,10 @@   resolveBuildTargets,  ) +#if MIN_VERSION_Cabal_syntax(3,17,0)+import Distribution.Fields (perror)+#endif+ -- | An input for 'executeAddConfig'. data AddConfig = AddConfig   { cnfOrigContents :: !ByteString@@ -229,12 +234,18 @@    packDescr <- case snd $ runParseResult $ parseGenericPackageDescription contents of     Left (_, err) ->-      errorWithCtx $ L.unlines $ map (showPError fileName) $ NE.toList err+      errorWithCtx $ L.unlines $ map (showPError fileName . toPError) $ NE.toList err     Right GenericPackageDescription {packageDescription = PackageDescription {specVersion = CabalSpecV1_0}} ->       errorWithCtx legacyErr     Right pd -> pure pd    pure (fields, packDescr)+  where+#if MIN_VERSION_Cabal_syntax(3,17,0)+    toPError = perror+#else+    toPError = id+#endif  readBuildTarget :: PackageDescription -> String -> Maybe ComponentName readBuildTarget pkg targetStr =
src/Distribution/Client/Rename.hs view
@@ -16,9 +16,9 @@ ) where  import Data.ByteString (ByteString)+import Data.ByteString.Builder qualified as Builder import Data.ByteString.Char8 qualified as B import Data.Char (isPunctuation, isSpace)-import Data.Foldable (fold) import Data.List qualified as L import Distribution.Client.Add (   TargetField (..),@@ -77,14 +77,14 @@ executeRenameConfig validator RenameConfig {cnfFields, cnfComponent, cnfOrigContents, cnfRenameFrom, cnfRenameTo, cnfTargetField} = do   let fieldsWithSource = annotateFieldsWithSource cnfOrigContents cnfFields       fieldsWithSource' = map replaceInSection fieldsWithSource-      newContents = foldMap fold fieldsWithSource'+      newContents = B.toStrict $ Builder.toLazyByteString $ foldMap (foldMap Builder.byteString) fieldsWithSource'   if validator cnfComponent newContents then Just newContents else Nothing   where     replaceInBS :: ByteString -> ByteString     replaceInBS hay       | B.null rest =           hay-      | not startsWithBoundary || not endsWithBoundary =+      | not startsWithBoundary || not endsWithBoundary || B.elem '\n' pref =           pref <> cnfRenameFrom <> replaceInBS suff       | otherwise =           pref <> cnfRenameTo <> replaceInBS suff
tests/Main.hs view
@@ -1,1434 +1,1448 @@ {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RecordWildCards #-}---- |--- Copyright:   (c) 2023 Bodigrim--- License:     BSD-3-Clause-module Main (main) where--import Data.Algorithm.Diff (Diff, PolyDiff (..), getDiff)-import Data.Char (isAlpha)-import Data.Maybe (mapMaybe)-import Data.String.QQ (s)-import System.Directory (findExecutable)-import System.Exit (ExitCode (..))-import System.IO.Temp (withSystemTempDirectory)-import System.Process (cwd, env, proc, readCreateProcessWithExitCode)-import Test.Tasty (TestTree, defaultMain, testGroup)-import Test.Tasty.Providers (IsTest (..), singleTest, testFailed, testPassed)--data CabalAddTest = CabalAddTest-  { catName :: String-  , catArgs :: [String]-  , catEnv :: [(String, String)]-  , catInput :: String-  , catOutput :: String-  }--instance IsTest CabalAddTest where-  testOptions = pure []-  run _opts CabalAddTest {..} _yieldProgress = do-    mCabalAddExe <- findExecutable "cabal-add"-    case mCabalAddExe of-      Nothing -> pure $ testFailed "cabal-add executable is not in PATH"-      Just cabalAddExe -> do-        let template = map (\c -> if isAlpha c then c else '_') catName-        withSystemTempDirectory template $ \tempDir -> do-          let cabalFileName = tempDir ++ "/" ++ template ++ ".cabal"-          writeFile cabalFileName catInput-          let crpr = (proc cabalAddExe catArgs) {cwd = Just tempDir, env = Just catEnv}-          (code, _out, err) <- readCreateProcessWithExitCode crpr ""-          case code of-            ExitFailure {} -> pure $ testFailed err-            ExitSuccess -> do-              output <- readFile cabalFileName-              pure $-                if output == catOutput-                  then testPassed ""-                  else testFailed $ prettyDiff $ getDiff (lines catOutput) (lines output)--prettyDiff :: [Diff String] -> String-prettyDiff =-  unlines-    . mapMaybe-      ( \case-          First xs -> Just $ '-' : xs-          Second ys -> Just $ '+' : ys-          Both xs _ -> Just $ ' ' : xs-      )--mkTest :: CabalAddTest -> TestTree-mkTest cat = singleTest (catName cat) cat--caseMultipleDependencies1 :: TestTree-caseMultipleDependencies1 =-  mkTest $-    CabalAddTest-      { catName = "add multiple dependencies 1"-      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:-    foo < 1 && >0.7,-    baz ^>= 2.0,-    base >=4.15 && <5-|]-      }--caseMultipleDependencies2 :: TestTree-caseMultipleDependencies2 =-  mkTest $-    CabalAddTest-      { catName = "add multiple dependencies 2"-      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends: base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends: foo < 1 && >0.7, baz ^>= 2.0, base >=4.15 && <5-|]-      }--caseMultipleDependencies3 :: TestTree-caseMultipleDependencies3 =-  mkTest $-    CabalAddTest-      { catName = "add multiple dependencies 3"-      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:   base >=4.15 && <5,-                   containers-|]-      , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:   foo < 1 && >0.7,-                   baz ^>= 2.0,-                   base >=4.15 && <5,-                   containers-|]-      }--caseMultipleDependencies4 :: TestTree-caseMultipleDependencies4 =-  mkTest $-    CabalAddTest-      { catName = "add multiple dependencies 4"-      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:   base >=4.15 && <5-                 , containers-                 , deepseq-|]-      , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:   foo < 1 && >0.7-                 , baz ^>= 2.0-                 , base >=4.15 && <5-                 , containers-                 , deepseq-|]-      }--caseLibraryInDescription :: TestTree-caseLibraryInDescription =-  mkTest $-    CabalAddTest-      { catName = "word 'library' in description"-      , catArgs = ["foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple-description:-  A library of basic functionality.--library-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple-description:-  A library of basic functionality.--library-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseImportFields1 :: TestTree-caseImportFields1 =-  mkTest $-    CabalAddTest-      { catName = "import fields 1"-      , catArgs = ["foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple--common foo-  build-depends: bar--library-  import: foo-  exposed-modules: Foo-|]-      , catOutput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple--common foo-  build-depends: bar--library-  import: foo-  build-depends: foo < 1 && >0.7, quux < 1-  exposed-modules: Foo-|]-      }--caseImportFields2 :: TestTree-caseImportFields2 =-  mkTest $-    CabalAddTest-      { catName = "import fields 2"-      , catArgs = ["foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple--common foo-  build-depends: bar--library-  Import : foo-  exposed-modules: Foo-|]-      , catOutput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple--common foo-  build-depends: bar--library-  Import : foo-  build-depends: foo < 1 && >0.7, quux < 1-  exposed-modules: Foo-|]-      }--caseImportFields3 :: TestTree-caseImportFields3 =-  mkTest $-    CabalAddTest-      { catName = "import fields 3"-      , catArgs = ["foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple--common foo-  build-depends: bar--library-  Import : foo-|]-      , catOutput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple--common foo-  build-depends: bar--library-  Import : foo-  build-depends: foo < 1 && >0.7, quux < 1-|]-      }--caseSublibraryTarget1 :: TestTree-caseSublibraryTarget1 =-  mkTest $-    CabalAddTest-      { catName = "sublibrary target 1"-      , catArgs = ["foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--library baz-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--library baz-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseSublibraryTarget2 :: TestTree-caseSublibraryTarget2 =-  mkTest $-    CabalAddTest-      { catName = "sublibrary target 2"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:-    base >=4.15 && <5--library baz-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:-    base >=4.15 && <5--library baz-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseExecutableTarget1 :: TestTree-caseExecutableTarget1 =-  mkTest $-    CabalAddTest-      { catName = "executable target 1"-      , catArgs = ["exe", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseExecutableTarget2 :: TestTree-caseExecutableTarget2 =-  mkTest $-    CabalAddTest-      { catName = "executable target 2"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseExecutableTarget3 :: TestTree-caseExecutableTarget3 =-  mkTest $-    CabalAddTest-      { catName = "executable target 3"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable "baz"-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable "baz"-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseExecutableTarget4 :: TestTree-caseExecutableTarget4 =-  mkTest $-    CabalAddTest-      { catName = "executable target 4"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common baz-  language: Haskell2010--executable baz-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common baz-  language: Haskell2010--executable baz-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseTestTarget1 :: TestTree-caseTestTarget1 =-  mkTest $-    CabalAddTest-      { catName = "test target 1"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common baz-  language: Haskell2010--test-suite baz-  type: exitcode-stdio-1.0-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common baz-  language: Haskell2010--test-suite baz-  type: exitcode-stdio-1.0-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseTestTarget2 :: TestTree-caseTestTarget2 =-  mkTest $-    CabalAddTest-      { catName = "test target 2"-      , catArgs = ["test:baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common baz-  language: Haskell2010--test-suite baz-  type: exitcode-stdio-1.0-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common baz-  language: Haskell2010--test-suite baz-  type: exitcode-stdio-1.0-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseCommonStanzaTarget1 :: TestTree-caseCommonStanzaTarget1 =-  mkTest $-    CabalAddTest-      { catName = "common stanza as a target 1"-      , catArgs = ["foo", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common foo-  language: Haskell2010-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--common foo-  build-depends: foo < 1 && >0.7, quux < 1-  language: Haskell2010-|]-      }--caseCommonStanzaTarget2 :: TestTree-caseCommonStanzaTarget2 =-  mkTest $-    CabalAddTest-      { catName = "common stanza as a target 2"-      , catArgs = ["foo", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--Common    foo-  language: Haskell2010-  build-depends:-    , base-    , containers-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--Common    foo-  language: Haskell2010-  build-depends:-    , foo < 1 && >0.7-    , quux < 1-    , base-    , containers-|]-      }--caseTwoSpacesInStanza :: TestTree-caseTwoSpacesInStanza =-  mkTest $-    CabalAddTest-      { catName = "two spaces in stanza"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable  baz-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable  baz-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseTitleCaseStanza1 :: TestTree-caseTitleCaseStanza1 =-  mkTest $-    CabalAddTest-      { catName = "title case in stanza 1"-      , catArgs = ["foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--Library-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--Library-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseTitleCaseStanza2 :: TestTree-caseTitleCaseStanza2 =-  mkTest $-    CabalAddTest-      { catName = "title case in stanza 2"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--Executable baz-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--Executable baz-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseTitleCaseBuildDepends :: TestTree-caseTitleCaseBuildDepends =-  mkTest $-    CabalAddTest-      { catName = "title case in build-depends"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-  Build-Depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-  Build-Depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--caseSharedComponentPrefixes :: TestTree-caseSharedComponentPrefixes =-  mkTest $-    CabalAddTest-      { catName = "shared component prefixes"-      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable bazzzy-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5--executable baz-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable bazzzy-  main-is: Main.hs-  build-depends:-    base >=4.15 && <5--executable baz-  main-is: Main.hs-  build-depends:-    foo < 1 && >0.7,-    quux < 1,-    base >=4.15 && <5-|]-      }--windowsLineEndings :: TestTree-windowsLineEndings =-  mkTest $-    CabalAddTest-      { catName = "Windows line endings"-      , catArgs = ["exe", "foo < 1 && >0.7", "quux < 1"]-      , catEnv = mempty-      , catInput =-          convertToWindowsLineEndings-            [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  main-is: Main.hs-|]-      , catOutput =-          convertToWindowsLineEndings-            [s|-name:          dummy-version:       0.1.0.0-cabal-version: 2.0-build-type:    Simple--executable baz-  build-depends: foo < 1 && >0.7, quux < 1-  main-is: Main.hs-|]-      }-  where-    convertToWindowsLineEndings :: String -> String-    convertToWindowsLineEndings = concatMap (\c -> if c == '\n' then ['\r', '\n'] else [c])--caseLeadingComma1 :: TestTree-caseLeadingComma1 =-  mkTest $-    CabalAddTest-      { catName = "build-depends start from comma 1"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends:-    , base >=4.15 && <5-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends:-    , baz ^>= 2.0-    , quux < 1-    , base >=4.15 && <5-|]-      }--caseLeadingComma2 :: TestTree-caseLeadingComma2 =-  mkTest $-    CabalAddTest-      { catName = "build-depends start from comma 2"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: ,base >=4.15 && <5-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: ,baz ^>= 2.0 ,quux < 1 ,base >=4.15 && <5-|]-      }--caseLeadingComma3 :: TestTree-caseLeadingComma3 =-  mkTest $-    CabalAddTest-      { catName = "build-depends start from comma 3"-      , catArgs = ["baz ^>= 2.0", "quux > 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: ,base >=4.15 && <5-                 ,containers-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: ,baz ^>= 2.0-                 ,quux > 1-                 ,base >=4.15 && <5-                 ,containers-|]-      }--caseConditionalBuildDepends :: TestTree-caseConditionalBuildDepends =-  mkTest $-    CabalAddTest-      { catName = "build-depends are under condition"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  if impl(ghc >= 9.6)-    build-depends:-      base >=4.15 && <5-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: baz ^>= 2.0, quux < 1-  if impl(ghc >= 9.6)-    build-depends:-      base >=4.15 && <5-|]-      }--caseEmptyComponent1 :: TestTree-caseEmptyComponent1 =-  mkTest $-    CabalAddTest-      { catName = "empty component 1"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library--executable bar-  main-is: Bar.hs-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library--  build-depends: baz ^>= 2.0, quux < 1--executable bar-  main-is: Bar.hs-|]-      }--caseEmptyComponent2 :: TestTree-caseEmptyComponent2 =-  mkTest $-    CabalAddTest-      { catName = "empty component 2"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: baz ^>= 2.0, quux < 1-|]-      }--caseEmptyComponent3 :: TestTree-caseEmptyComponent3 =-  mkTest $-    CabalAddTest-      { catName = "empty component 3"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: baz ^>= 2.0, quux < 1-|]-      }--caseEmptyBuildDepends :: TestTree-caseEmptyBuildDepends =-  mkTest $-    CabalAddTest-      { catName = "empty build-depends"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends:-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--library-  build-depends: baz ^>= 2.0, quux < 1-  build-depends:-|]-      }--caseComponentInBraces :: TestTree-caseComponentInBraces =-  mkTest $-    CabalAddTest-      { catName = "component in figure braces"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--Library {-  Build-Depends: base >= 4 && < 5-}-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--Library {-  Build-Depends: baz ^>= 2.0, quux < 1, base >= 4 && < 5-}-|]-      }--caseCommentsWithCommas :: TestTree-caseCommentsWithCommas =-  mkTest $-    CabalAddTest-      { catName = "comments with commas"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  main-is:       Main.hs-  build-depends:    magda,-                    -- Something, which-                    -- contains commas.-                    base-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  main-is:       Main.hs-  build-depends:    baz ^>= 2.0, quux < 1, magda,-                    -- Something, which-                    -- contains commas.-                    base-|]-      }--caseCommentsWithoutCommas :: TestTree-caseCommentsWithoutCommas =-  mkTest $-    CabalAddTest-      { catName = "comments without commas"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  main-is:       Main.hs-  build-depends:  magda,-                  -- Something without commas-                  base-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  main-is:       Main.hs-  build-depends:  baz ^>= 2.0, quux < 1, magda,-                  -- Something without commas-                  base-|]-      }--caseDependenciesOnTheSameLine :: TestTree-caseDependenciesOnTheSameLine =-  mkTest $-    CabalAddTest-      { catName = "all build-deps on the same line"-      , catArgs = ["baz ^>= 2.0", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   magda, base-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   baz ^>= 2.0, quux < 1, magda, base-|]-      }--caseIgnoreAddArgument :: TestTree-caseIgnoreAddArgument =-  mkTest $-    CabalAddTest-      { catName = "ignore add as the first command-line argument"-      , catArgs = ["add", "baz ^>= 2.0", "quux < 1"]-      , catEnv = [("CABAL", "/fake/usr/bin/local/cabal")]-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   magda, base-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   baz ^>= 2.0, quux < 1, magda, base-|]-      }--caseDoNotIgnoreAddArgument :: TestTree-caseDoNotIgnoreAddArgument =-  mkTest $-    CabalAddTest-      { catName = "do not ignore add as the second command-line argument"-      , catArgs = ["baz ^>= 2.0", "add", "quux < 1"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   magda, base-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   baz ^>= 2.0, add, quux < 1, magda, base-|]-      }--caseSublibraryDependency :: TestTree-caseSublibraryDependency =-  mkTest $-    CabalAddTest-      { catName = "sublibrary as a dependency"-      , catArgs = ["foo:bar"]-      , catEnv = mempty-      , catInput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   magda, base-|]-      , catOutput =-          [s|-cabal-version: 3.6-name:          dummy-version:       0.1-build-type:    Simple--executable dagda-  build-depends:   foo:bar, magda, base-|]-      }--caseSpecialDependencyName1 :: TestTree-caseSpecialDependencyName1 =-  mkTest $-    CabalAddTest-      { catName = "add dependency named 'add'"-      , catArgs = ["add"]-      , catEnv = mempty-      , catInput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:-    base >=4.15 && <5-|]-      , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple--library-  build-depends:-    add,-    base >=4.15 && <5-|]+{-# LANGUAGE MultilineStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-}++{- HLINT ignore "Avoid restricted function" -}++-- |+-- Copyright:   (c) 2023 Bodigrim+-- License:     BSD-3-Clause+module Main (main) where++import Data.Algorithm.Diff (Diff, PolyDiff (..), getDiff)+import Data.ByteString.Lazy (LazyByteString)+import Data.ByteString.Lazy.Char8 qualified as BL+import Data.Char (isAlpha)+import Data.Maybe (mapMaybe)+import Data.String (fromString)+import System.Directory (findExecutable)+import System.Exit (ExitCode (..))+import System.File.OsPath (readFile, writeFile)+import System.IO.Temp.OsPath (withSystemTempDirectory)+import System.IO.Unsafe (unsafePerformIO)+import System.OsPath (decodeFS, encodeFS, osp, (<.>), (</>))+import System.Process (cwd, env, proc, readCreateProcessWithExitCode)+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.Providers (IsTest (..), singleTest, testFailed, testPassed)+import Prelude hiding (readFile, writeFile)++data CabalAddTest = CabalAddTest+  { catName :: String+  , catArgs :: [String]+  , catEnv :: [(String, String)]+  , catInput :: String+  , catOutput :: String+  }++instance IsTest CabalAddTest where+  testOptions = pure []+  run _opts CabalAddTest {..} _yieldProgress = do+    mCabalAddExe <- findExecutable "cabal-add"+    case mCabalAddExe of+      Nothing -> pure $ testFailed "cabal-add executable is not in PATH"+      Just cabalAddExe -> do+        let template = unsafePerformIO $ encodeFS $ map (\c -> if isAlpha c then c else '_') catName+        withSystemTempDirectory template $ \tempDir -> do+          let cabalFileName = tempDir </> template <.> [osp|cabal|]+          writeFile cabalFileName (fromString catInput)+          let crpr =+                (proc cabalAddExe catArgs)+                  { cwd = Just $ unsafePerformIO $ decodeFS tempDir+                  , env = Just catEnv+                  }+          (code, _out, err) <- readCreateProcessWithExitCode crpr ""+          case code of+            ExitFailure errCode -> pure $ testFailed $ "ExitFailure " ++ show errCode ++ "\n" ++ err+            ExitSuccess -> do+              output <- readFile cabalFileName+              let catOutput' = fromString catOutput+              pure $+                if BL.lines output == BL.lines catOutput'+                  then testPassed ""+                  else testFailed $ BL.unpack $ prettyDiff $ getDiff (BL.lines catOutput') (BL.lines output)++prettyDiff :: [Diff LazyByteString] -> LazyByteString+prettyDiff =+  BL.unlines+    . mapMaybe+      ( \case+          First xs -> Just $ BL.cons '-' xs+          Second ys -> Just $ BL.cons '+' ys+          Both xs _ -> Just $ BL.cons ' ' xs+      )++mkTest :: CabalAddTest -> TestTree+mkTest cat = singleTest (catName cat) cat++caseMultipleDependencies1 :: TestTree+caseMultipleDependencies1 =+  mkTest $+    CabalAddTest+      { catName = "add multiple dependencies 1"+      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:+              foo < 1 && >0.7,+              baz ^>= 2.0,+              base >=4.15 && <5+          """+      }++caseMultipleDependencies2 :: TestTree+caseMultipleDependencies2 =+  mkTest $+    CabalAddTest+      { catName = "add multiple dependencies 2"+      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends: base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends: foo < 1 && >0.7, baz ^>= 2.0, base >=4.15 && <5+          """+      }++caseMultipleDependencies3 :: TestTree+caseMultipleDependencies3 =+  mkTest $+    CabalAddTest+      { catName = "add multiple dependencies 3"+      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:   base >=4.15 && <5,+                             containers+          """+      , catOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:   foo < 1 && >0.7,+                             baz ^>= 2.0,+                             base >=4.15 && <5,+                             containers+          """+      }++caseMultipleDependencies4 :: TestTree+caseMultipleDependencies4 =+  mkTest $+    CabalAddTest+      { catName = "add multiple dependencies 4"+      , catArgs = ["foo < 1 && >0.7", "baz ^>= 2.0"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:   base >=4.15 && <5+                           , containers+                           , deepseq+          """+      , catOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:   foo < 1 && >0.7+                           , baz ^>= 2.0+                           , base >=4.15 && <5+                           , containers+                           , deepseq+          """+      }++caseLibraryInDescription :: TestTree+caseLibraryInDescription =+  mkTest $+    CabalAddTest+      { catName = "word 'library' in description"+      , catArgs = ["foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple+          description:+            A library of basic functionality.++          library+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple+          description:+            A library of basic functionality.++          library+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseImportFields1 :: TestTree+caseImportFields1 =+  mkTest $+    CabalAddTest+      { catName = "import fields 1"+      , catArgs = ["foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple++          common foo+            build-depends: bar++          library+            import: foo+            exposed-modules: Foo+          """+      , catOutput =+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple++          common foo+            build-depends: bar++          library+            import: foo+            build-depends: foo < 1 && >0.7, quux < 1+            exposed-modules: Foo+          """+      }++caseImportFields2 :: TestTree+caseImportFields2 =+  mkTest $+    CabalAddTest+      { catName = "import fields 2"+      , catArgs = ["foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple++          common foo+            build-depends: bar++          library+            Import : foo+            exposed-modules: Foo+          """+      , catOutput =+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple++          common foo+            build-depends: bar++          library+            Import : foo+            build-depends: foo < 1 && >0.7, quux < 1+            exposed-modules: Foo+          """+      }++caseImportFields3 :: TestTree+caseImportFields3 =+  mkTest $+    CabalAddTest+      { catName = "import fields 3"+      , catArgs = ["foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple++          common foo+            build-depends: bar++          library+            Import : foo+          """+      , catOutput =+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple++          common foo+            build-depends: bar++          library+            Import : foo+            build-depends: foo < 1 && >0.7, quux < 1+          """+      }++caseSublibraryTarget1 :: TestTree+caseSublibraryTarget1 =+  mkTest $+    CabalAddTest+      { catName = "sublibrary target 1"+      , catArgs = ["foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          library baz+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          library baz+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseSublibraryTarget2 :: TestTree+caseSublibraryTarget2 =+  mkTest $+    CabalAddTest+      { catName = "sublibrary target 2"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:+              base >=4.15 && <5++          library baz+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:+              base >=4.15 && <5++          library baz+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseExecutableTarget1 :: TestTree+caseExecutableTarget1 =+  mkTest $+    CabalAddTest+      { catName = "executable target 1"+      , catArgs = ["exe", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable baz+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable baz+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseExecutableTarget2 :: TestTree+caseExecutableTarget2 =+  mkTest $+    CabalAddTest+      { catName = "executable target 2"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable baz+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable baz+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseExecutableTarget3 :: TestTree+caseExecutableTarget3 =+  mkTest $+    CabalAddTest+      { catName = "executable target 3"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable "baz"+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable "baz"+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseExecutableTarget4 :: TestTree+caseExecutableTarget4 =+  mkTest $+    CabalAddTest+      { catName = "executable target 4"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common baz+            language: Haskell2010++          executable baz+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common baz+            language: Haskell2010++          executable baz+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseTestTarget1 :: TestTree+caseTestTarget1 =+  mkTest $+    CabalAddTest+      { catName = "test target 1"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common baz+            language: Haskell2010++          test-suite baz+            type: exitcode-stdio-1.0+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common baz+            language: Haskell2010++          test-suite baz+            type: exitcode-stdio-1.0+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseTestTarget2 :: TestTree+caseTestTarget2 =+  mkTest $+    CabalAddTest+      { catName = "test target 2"+      , catArgs = ["test:baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common baz+            language: Haskell2010++          test-suite baz+            type: exitcode-stdio-1.0+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common baz+            language: Haskell2010++          test-suite baz+            type: exitcode-stdio-1.0+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseCommonStanzaTarget1 :: TestTree+caseCommonStanzaTarget1 =+  mkTest $+    CabalAddTest+      { catName = "common stanza as a target 1"+      , catArgs = ["foo", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common foo+            language: Haskell2010+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          common foo+            build-depends: foo < 1 && >0.7, quux < 1+            language: Haskell2010+          """+      }++caseCommonStanzaTarget2 :: TestTree+caseCommonStanzaTarget2 =+  mkTest $+    CabalAddTest+      { catName = "common stanza as a target 2"+      , catArgs = ["foo", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          Common    foo+            language: Haskell2010+            build-depends:+              , base+              , containers+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          Common    foo+            language: Haskell2010+            build-depends:+              , foo < 1 && >0.7+              , quux < 1+              , base+              , containers+          """+      }++caseTwoSpacesInStanza :: TestTree+caseTwoSpacesInStanza =+  mkTest $+    CabalAddTest+      { catName = "two spaces in stanza"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable  baz+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable  baz+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseTitleCaseStanza1 :: TestTree+caseTitleCaseStanza1 =+  mkTest $+    CabalAddTest+      { catName = "title case in stanza 1"+      , catArgs = ["foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          Library+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          Library+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseTitleCaseStanza2 :: TestTree+caseTitleCaseStanza2 =+  mkTest $+    CabalAddTest+      { catName = "title case in stanza 2"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          Executable baz+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          Executable baz+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseTitleCaseBuildDepends :: TestTree+caseTitleCaseBuildDepends =+  mkTest $+    CabalAddTest+      { catName = "title case in build-depends"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable baz+            main-is: Main.hs+            Build-Depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable baz+            main-is: Main.hs+            Build-Depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++caseSharedComponentPrefixes :: TestTree+caseSharedComponentPrefixes =+  mkTest $+    CabalAddTest+      { catName = "shared component prefixes"+      , catArgs = ["baz", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable bazzzy+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5++          executable baz+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.1.0.0+          cabal-version: 2.0+          build-type:    Simple++          executable bazzzy+            main-is: Main.hs+            build-depends:+              base >=4.15 && <5++          executable baz+            main-is: Main.hs+            build-depends:+              foo < 1 && >0.7,+              quux < 1,+              base >=4.15 && <5+          """+      }++windowsLineEndings :: TestTree+windowsLineEndings =+  mkTest $+    CabalAddTest+      { catName = "Windows line endings"+      , catArgs = ["exe", "foo < 1 && >0.7", "quux < 1"]+      , catEnv = mempty+      , catInput =+          convertToWindowsLineEndings+            """+            name:          dummy+            version:       0.1.0.0+            cabal-version: 2.0+            build-type:    Simple++            executable baz+              main-is: Main.hs+            """+      , catOutput =+          convertToWindowsLineEndings+            """+            name:          dummy+            version:       0.1.0.0+            cabal-version: 2.0+            build-type:    Simple++            executable baz+              build-depends: foo < 1 && >0.7, quux < 1+              main-is: Main.hs+            """+      }+  where+    convertToWindowsLineEndings :: String -> String+    convertToWindowsLineEndings = concatMap (\c -> if c == '\n' then ['\r', '\n'] else [c])++caseLeadingComma1 :: TestTree+caseLeadingComma1 =+  mkTest $+    CabalAddTest+      { catName = "build-depends start from comma 1"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends:+              , base >=4.15 && <5+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends:+              , baz ^>= 2.0+              , quux < 1+              , base >=4.15 && <5+          """+      }++caseLeadingComma2 :: TestTree+caseLeadingComma2 =+  mkTest $+    CabalAddTest+      { catName = "build-depends start from comma 2"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: ,base >=4.15 && <5+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: ,baz ^>= 2.0 ,quux < 1 ,base >=4.15 && <5+          """+      }++caseLeadingComma3 :: TestTree+caseLeadingComma3 =+  mkTest $+    CabalAddTest+      { catName = "build-depends start from comma 3"+      , catArgs = ["baz ^>= 2.0", "quux > 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: ,base >=4.15 && <5+                           ,containers+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: ,baz ^>= 2.0+                           ,quux > 1+                           ,base >=4.15 && <5+                           ,containers+          """+      }++caseConditionalBuildDepends :: TestTree+caseConditionalBuildDepends =+  mkTest $+    CabalAddTest+      { catName = "build-depends are under condition"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            if impl(ghc >= 9.6)+              build-depends:+                base >=4.15 && <5+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: baz ^>= 2.0, quux < 1+            if impl(ghc >= 9.6)+              build-depends:+                base >=4.15 && <5+          """+      }++caseEmptyComponent1 :: TestTree+caseEmptyComponent1 =+  mkTest $+    CabalAddTest+      { catName = "empty component 1"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library++          executable bar+            main-is: Bar.hs+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library++            build-depends: baz ^>= 2.0, quux < 1++          executable bar+            main-is: Bar.hs+          """+      }++caseEmptyComponent2 :: TestTree+caseEmptyComponent2 =+  mkTest $+    CabalAddTest+      { catName = "empty component 2"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: baz ^>= 2.0, quux < 1+          """+      }++caseEmptyComponent3 :: TestTree+caseEmptyComponent3 =+  mkTest $+    CabalAddTest+      { catName = "empty component 3"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library"""+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: baz ^>= 2.0, quux < 1+          """+      }++caseEmptyBuildDepends :: TestTree+caseEmptyBuildDepends =+  mkTest $+    CabalAddTest+      { catName = "empty build-depends"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends:+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          library+            build-depends: baz ^>= 2.0, quux < 1+            build-depends:+          """+      }++caseComponentInBraces :: TestTree+caseComponentInBraces =+  mkTest $+    CabalAddTest+      { catName = "component in figure braces"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          Library {+            Build-Depends: base >= 4 && < 5+          }+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          Library {+            Build-Depends: baz ^>= 2.0, quux < 1, base >= 4 && < 5+          }+          """+      }++caseCommentsWithCommas :: TestTree+caseCommentsWithCommas =+  mkTest $+    CabalAddTest+      { catName = "comments with commas"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            main-is:       Main.hs+            build-depends:    magda,+                              -- Something, which+                              -- contains commas.+                              base+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            main-is:       Main.hs+            build-depends:    baz ^>= 2.0, quux < 1, magda,+                              -- Something, which+                              -- contains commas.+                              base+          """+      }++caseCommentsWithoutCommas :: TestTree+caseCommentsWithoutCommas =+  mkTest $+    CabalAddTest+      { catName = "comments without commas"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            main-is:       Main.hs+            build-depends:  magda,+                            -- Something without commas+                            base+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            main-is:       Main.hs+            build-depends:  baz ^>= 2.0, quux < 1, magda,+                            -- Something without commas+                            base+          """+      }++caseDependenciesOnTheSameLine :: TestTree+caseDependenciesOnTheSameLine =+  mkTest $+    CabalAddTest+      { catName = "all build-deps on the same line"+      , catArgs = ["baz ^>= 2.0", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   magda, base+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   baz ^>= 2.0, quux < 1, magda, base+          """+      }++caseIgnoreAddArgument :: TestTree+caseIgnoreAddArgument =+  mkTest $+    CabalAddTest+      { catName = "ignore add as the first command-line argument"+      , catArgs = ["add", "baz ^>= 2.0", "quux < 1"]+      , catEnv = [("CABAL", "/fake/usr/bin/local/cabal")]+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   magda, base+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   baz ^>= 2.0, quux < 1, magda, base+          """+      }++caseDoNotIgnoreAddArgument :: TestTree+caseDoNotIgnoreAddArgument =+  mkTest $+    CabalAddTest+      { catName = "do not ignore add as the second command-line argument"+      , catArgs = ["baz ^>= 2.0", "add", "quux < 1"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   magda, base+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   baz ^>= 2.0, add, quux < 1, magda, base+          """+      }++caseSublibraryDependency :: TestTree+caseSublibraryDependency =+  mkTest $+    CabalAddTest+      { catName = "sublibrary as a dependency"+      , catArgs = ["foo:bar"]+      , catEnv = mempty+      , catInput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   magda, base+          """+      , catOutput =+          """+          cabal-version: 3.6+          name:          dummy+          version:       0.1+          build-type:    Simple++          executable dagda+            build-depends:   foo:bar, magda, base+          """+      }++caseSpecialDependencyName1 :: TestTree+caseSpecialDependencyName1 =+  mkTest $+    CabalAddTest+      { catName = "add dependency named 'add'"+      , catArgs = ["add"]+      , catEnv = mempty+      , catInput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:+              base >=4.15 && <5+          """+      , catOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            build-depends:+              add,+              base >=4.15 && <5+          """       }  main :: IO ()
tests/UnitTests.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultilineStrings #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RecordWildCards #-}  -- |@@ -13,7 +13,6 @@ import Data.ByteString.Char8 qualified as B import Data.List.NonEmpty qualified as NE import Data.Maybe (mapMaybe)-import Data.String.QQ (s) import Distribution.Client.Add (AddConfig (..), TargetField (..), executeAddConfig, parseCabalFile) import Distribution.Client.Rename (RenameConfig (..), executeRenameConfig) import Distribution.Fields.Field (Field)@@ -79,31 +78,31 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  build-depends:-    foo < 1 && >0.7,-    baz ^>= 2.0,-    base >=4.15 && <5-|]+          library+            build-depends:+              foo < 1 && >0.7,+              baz ^>= 2.0,+              base >=4.15 && <5+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-|]+      library+        build-depends:+          base >=4.15 && <5+      """  caseMultipleExposedModules1 :: TestTree caseMultipleExposedModules1 =@@ -119,31 +118,31 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2, Main, OtherModule.Mine-|]+          library+            build-depends:+              base >=4.15 && <5+            exposed-modules: Test.Mod1, Test.Mod2, Main, OtherModule.Mine+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Main, OtherModule.Mine-|]+      library+        build-depends:+          base >=4.15 && <5+        exposed-modules: Main, OtherModule.Mine+      """  caseMultipleExposedModulesUsingSpaces :: TestTree caseMultipleExposedModulesUsingSpaces =@@ -159,31 +158,31 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1 Test.Mod2 Main OtherModule.Mine-|]+          library+            build-depends:+              base >=4.15 && <5+            exposed-modules: Test.Mod1 Test.Mod2 Main OtherModule.Mine+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Main OtherModule.Mine-|]+      library+        build-depends:+          base >=4.15 && <5+        exposed-modules: Main OtherModule.Mine+      """  caseMultipleOtherModules :: TestTree caseMultipleOtherModules =@@ -199,45 +198,45 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1 Test.Mod2-test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:-    Test.Mod1,-    Mod3,-    Dir.Mod1,-    Dir.Mod2-|]+          library+            build-depends:+              base >=4.15 && <5+            exposed-modules: Test.Mod1 Test.Mod2+          test-suite testss+            main-is: Main.hs+            type: exitcode-stdio-1.0+            other-modules:+              Test.Mod1,+              Mod3,+              Dir.Mod1,+              Dir.Mod2+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1 Test.Mod2-test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:-    Dir.Mod1,-    Dir.Mod2-|]+      library+        build-depends:+          base >=4.15 && <5+        exposed-modules: Test.Mod1 Test.Mod2+      test-suite testss+        main-is: Main.hs+        type: exitcode-stdio-1.0+        other-modules:+          Dir.Mod1,+          Dir.Mod2+      """  caseMultipleOtherModulesUsingSpaces :: TestTree caseMultipleOtherModulesUsingSpaces =@@ -253,47 +252,47 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:-    Test.Mod1-    Mod3-    Dir.Mod1-    Dir.Mod2+          test-suite testss+            main-is: Main.hs+            type: exitcode-stdio-1.0+            other-modules:+              Test.Mod1+              Mod3+              Dir.Mod1+              Dir.Mod2 -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2-|]+          library+            build-depends:+              base >=4.15 && <5+            exposed-modules: Test.Mod1, Test.Mod2+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:-    Dir.Mod1-    Dir.Mod2+      test-suite testss+        main-is: Main.hs+        type: exitcode-stdio-1.0+        other-modules:+          Dir.Mod1+          Dir.Mod2 -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2-|]+      library+        build-depends:+          base >=4.15 && <5+        exposed-modules: Test.Mod1, Test.Mod2+      """  caseMultipleOtherModulesUsingLeadingCommas :: TestTree caseMultipleOtherModulesUsingLeadingCommas =@@ -309,45 +308,45 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:  Test.Mod1-                , Mod3-                , Dir.Mod1-                , Dir.Mod2+          test-suite testss+            main-is: Main.hs+            type: exitcode-stdio-1.0+            other-modules:  Test.Mod1+                          , Mod3+                          , Dir.Mod1+                          , Dir.Mod2 -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2-|]+          library+            build-depends:+              base >=4.15 && <5+            exposed-modules: Test.Mod1, Test.Mod2+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:  Dir.Mod1-                , Dir.Mod2+      test-suite testss+        main-is: Main.hs+        type: exitcode-stdio-1.0+        other-modules:  Dir.Mod1+                      , Dir.Mod2 -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2-|]+      library+        build-depends:+          base >=4.15 && <5+        exposed-modules: Test.Mod1, Test.Mod2+      """  caseMultipleOtherModulesUsingLeadingSpaces :: TestTree caseMultipleOtherModulesUsingLeadingSpaces =@@ -363,45 +362,45 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:  Test.Mod1-                  Mod3-                  Dir.Mod1-                  Dir.Mod2+          test-suite testss+            main-is: Main.hs+            type: exitcode-stdio-1.0+            other-modules:  Test.Mod1+                            Mod3+                            Dir.Mod1+                            Dir.Mod2 -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2-|]+          library+            build-depends:+              base >=4.15 && <5+            exposed-modules: Test.Mod1, Test.Mod2+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -test-suite testss-  main-is: Main.hs-  type: exitcode-stdio-1.0-  other-modules:  Dir.Mod1-                  Dir.Mod2+      test-suite testss+        main-is: Main.hs+        type: exitcode-stdio-1.0+        other-modules:  Dir.Mod1+                        Dir.Mod2 -library-  build-depends:-    base >=4.15 && <5-  exposed-modules: Test.Mod1, Test.Mod2-|]+      library+        build-depends:+          base >=4.15 && <5+        exposed-modules: Test.Mod1, Test.Mod2+      """  caseMultipleOtherModulesWithImportFields :: TestTree caseMultipleOtherModulesWithImportFields =@@ -417,40 +416,40 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple -common foo-  build-depends: bar-  other-modules: Other+          common foo+            build-depends: bar+            other-modules: Other -library-  import: foo-  other-modules: This.Dir.Mod1, Mod3-  build-depends: foo < 1 && >0.7, quux < 1-  exposed-modules: Foo-|]+          library+            import: foo+            other-modules: This.Dir.Mod1, Mod3+            build-depends: foo < 1 && >0.7, quux < 1+            exposed-modules: Foo+          """       }   where     inContents =-      [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple+      """+      cabal-version: 2.2+      name:          dummy+      version:       0.13.0.0+      build-type:    Simple -common foo-  build-depends: bar-  other-modules: Other+      common foo+        build-depends: bar+        other-modules: Other -library-  import: foo-  build-depends: foo < 1 && >0.7, quux < 1-  exposed-modules: Foo-|]+      library+        import: foo+        build-depends: foo < 1 && >0.7, quux < 1+        exposed-modules: Foo+      """  caseMultipleOtherModulesWithImportFields2 :: TestTree caseMultipleOtherModulesWithImportFields2 =@@ -466,40 +465,40 @@             , cnfOrigContents = inContents             }       , catOutput =-          [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple+          """+          cabal-version: 2.2+          name:          dummy+          version:       0.13.0.0+          build-type:    Simple -common foo-  build-depends: bar-  other-modules: Other+          common foo+            build-depends: bar+            other-modules: Other -library-  Import: foo-  other-modules: This.Dir.Mod1, Mod3-  build-depends: foo < 1 && >0.7, quux < 1-  exposed-modules: Foo-|]+          library+            Import: foo+            other-modules: This.Dir.Mod1, Mod3+            build-depends: foo < 1 && >0.7, quux < 1+            exposed-modules: Foo+          """       }   where     inContents =-      [s|-cabal-version: 2.2-name:          dummy-version:       0.13.0.0-build-type:    Simple+      """+      cabal-version: 2.2+      name:          dummy+      version:       0.13.0.0+      build-type:    Simple -common foo-  build-depends: bar-  other-modules: Other+      common foo+        build-depends: bar+        other-modules: Other -library-  Import: foo-  build-depends: foo < 1 && >0.7, quux < 1-  exposed-modules: Foo-|]+      library+        Import: foo+        build-depends: foo < 1 && >0.7, quux < 1+        exposed-modules: Foo+      """  caseRenameDependency1 :: TestTree caseRenameDependency1 =@@ -516,43 +515,43 @@             , cnfRenameTo = "relude"             }       , crtOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  build-depends:-    relude >=4.15 && <5,-    base-foo,-    foo-base+          library+            build-depends:+              relude >=4.15 && <5,+              base-foo,+              foo-base -benchmark foo-  type: exitcode-stdio-1.0-  main-is: Main-  build-depends: base-|]+          benchmark foo+            type: exitcode-stdio-1.0+            main-is: Main+            build-depends: base+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  build-depends:-    base >=4.15 && <5,-    base-foo,-    foo-base+      library+        build-depends:+          base >=4.15 && <5,+          base-foo,+          foo-base -benchmark foo-  type: exitcode-stdio-1.0-  main-is: Main-  build-depends: base-|]+      benchmark foo+        type: exitcode-stdio-1.0+        main-is: Main+        build-depends: base+      """  caseRenameDependency2 :: TestTree caseRenameDependency2 =@@ -569,29 +568,29 @@             , cnfRenameTo = "relude"             }       , crtOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  build-depends:-    relude>=4, relude<4, relude==4.9.0.0, relude^>=4.0, relude(>4 && <5)-|]+          library+            build-depends:+              relude>=4, relude<4, relude==4.9.0.0, relude^>=4.0, relude(>4 && <5)+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  build-depends:-    base>=4, base<4, base==4.9.0.0, base^>=4.0, base(>4 && <5)-|]+      library+        build-depends:+          base>=4, base<4, base==4.9.0.0, base^>=4.0, base(>4 && <5)+      """  caseRenameExposedModule1 :: TestTree caseRenameExposedModule1 =@@ -608,38 +607,81 @@             , cnfRenameTo = "Data.Quux"             }       , crtOutput =-          [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple -library-  exposed-modules: Data.Quux, Data.Foo.Bar, Data.Foo.Baz+          library+            exposed-modules: Data.Quux, Data.Foo.Bar, Data.Foo.Baz -benchmark foo-  type: exitcode-stdio-1.0-  main-is: Main-  exposed-modules: Data.Foo-|]+          benchmark foo+            type: exitcode-stdio-1.0+            main-is: Main+            exposed-modules: Data.Foo+          """       }   where     inContents =-      [s|-name:          dummy-version:       0.13.0.0-cabal-version: 2.0-build-type:    Simple+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple -library-  exposed-modules: Data.Foo, Data.Foo.Bar, Data.Foo.Baz+      library+        exposed-modules: Data.Foo, Data.Foo.Bar, Data.Foo.Baz -benchmark foo-  type: exitcode-stdio-1.0-  main-is: Main-  exposed-modules: Data.Foo-|]+      benchmark foo+        type: exitcode-stdio-1.0+        main-is: Main+        exposed-modules: Data.Foo+      """ +caseRenameExposedModule2 :: TestTree+caseRenameExposedModule2 =+  mkRenameTest $+    CabalRenameTest+      { crtName = "rename exposed module with comments"+      , crtConfig =+          RenameConfig+            { cnfComponent = Right $ CLibName LMainLibName+            , cnfTargetField = ExposedModules+            , cnfFields = parseCabalFileOrError inContents+            , cnfOrigContents = inContents+            , cnfRenameFrom = "Data.Foo"+            , cnfRenameTo = "Data.Quux"+            }+      , crtOutput =+          """+          name:          dummy+          version:       0.13.0.0+          cabal-version: 2.0+          build-type:    Simple++          library+            exposed-modules:+              -- Data.Foo as a comment+              Data.Quux+              -- Data.Foo again+          """+      }+  where+    inContents =+      """+      name:          dummy+      version:       0.13.0.0+      cabal-version: 2.0+      build-type:    Simple++      library+        exposed-modules:+          -- Data.Foo as a comment+          Data.Foo+          -- Data.Foo again+      """+ prettyDiff :: [Diff String] -> String prettyDiff =   unlines@@ -673,4 +715,5 @@       , caseRenameDependency1       , caseRenameDependency2       , caseRenameExposedModule1+      , caseRenameExposedModule2       ]