diff --git a/Cabal/Cabal.cabal b/Cabal/Cabal.cabal index a6106ec6086892fcef74eba3ee15bc8c92cfd131..847a250a6c96516bf4a34d8c6554f7fac24cccda 100644 --- a/Cabal/Cabal.cabal +++ b/Cabal/Cabal.cabal @@ -50,6 +50,10 @@ extra-source-files: tests/ParserTests/errors/issue-5055.errors tests/ParserTests/errors/leading-comma.cabal tests/ParserTests/errors/leading-comma.errors + tests/ParserTests/errors/noVersion.cabal + tests/ParserTests/errors/noVersion.errors + tests/ParserTests/errors/noVersion2.cabal + tests/ParserTests/errors/noVersion2.errors tests/ParserTests/errors/range-ge-wild.cabal tests/ParserTests/errors/range-ge-wild.errors tests/ParserTests/ipi/Includes2.cabal @@ -101,6 +105,9 @@ extra-source-files: tests/ParserTests/regressions/leading-comma.cabal tests/ParserTests/regressions/leading-comma.expr tests/ParserTests/regressions/leading-comma.format + tests/ParserTests/regressions/noVersion.cabal + tests/ParserTests/regressions/noVersion.expr + tests/ParserTests/regressions/noVersion.format tests/ParserTests/regressions/nothing-unicode.cabal tests/ParserTests/regressions/nothing-unicode.check tests/ParserTests/regressions/nothing-unicode.expr diff --git a/Cabal/Distribution/CabalSpecVersion.hs b/Cabal/Distribution/CabalSpecVersion.hs index 9e8b4f6a27fb9c29f0ba6e6d76c166b3c8a58160..5a503c31d88d1838a3a9a609d87126158b120dc5 100644 --- a/Cabal/Distribution/CabalSpecVersion.hs +++ b/Cabal/Distribution/CabalSpecVersion.hs @@ -12,6 +12,7 @@ import qualified Data.Set as Set -- data CabalSpecVersion = CabalSpecOld + | CabalSpecV1_22 | CabalSpecV1_24 | CabalSpecV2_0 | CabalSpecV2_2 @@ -22,6 +23,7 @@ cabalSpecLatest = CabalSpecV2_2 cabalSpecFeatures :: CabalSpecVersion -> Set.Set CabalFeature cabalSpecFeatures CabalSpecOld = Set.empty +cabalSpecFeatures CabalSpecV1_22 = Set.empty cabalSpecFeatures CabalSpecV1_24 = Set.empty cabalSpecFeatures CabalSpecV2_0 = Set.empty cabalSpecFeatures CabalSpecV2_2 = Set.fromList @@ -30,7 +32,8 @@ cabalSpecFeatures CabalSpecV2_2 = Set.fromList ] cabalSpecSupports :: CabalSpecVersion -> [Int] -> Bool -cabalSpecSupports CabalSpecOld v = v < [1,23] +cabalSpecSupports CabalSpecOld v = v < [1,21] +cabalSpecSupports CabalSpecV1_22 v = v < [1,23] cabalSpecSupports CabalSpecV1_24 v = v < [1,25] cabalSpecSupports CabalSpecV2_0 v = v < [2,1] cabalSpecSupports CabalSpecV2_2 _ = True diff --git a/Cabal/Distribution/PackageDescription/Parsec.hs b/Cabal/Distribution/PackageDescription/Parsec.hs index f94a09c5e7e14251ac02af418108df424f5fbb34..e3e32ea48a0a50e70619f3b61bff26916e6054fe 100644 --- a/Cabal/Distribution/PackageDescription/Parsec.hs +++ b/Cabal/Distribution/PackageDescription/Parsec.hs @@ -203,6 +203,7 @@ parseGenericPackageDescription' cabalVerM lexWarnings utf8WarnPos fs = do | cabalVer >= mkVersion [2,1] = CabalSpecV2_2 | cabalVer >= mkVersion [1,25] = CabalSpecV2_0 | cabalVer >= mkVersion [1,23] = CabalSpecV1_24 + | cabalVer >= mkVersion [1,21] = CabalSpecV1_22 | otherwise = CabalSpecOld -- reset cabal version diff --git a/Cabal/Distribution/Types/VersionRange.hs b/Cabal/Distribution/Types/VersionRange.hs index fbcabcdb35f5c1484322a513403f441a5bdf3adc..c0118f88e639f6fcc30e410a761aa7f4efcdf954 100644 --- a/Cabal/Distribution/Types/VersionRange.hs +++ b/Cabal/Distribution/Types/VersionRange.hs @@ -45,6 +45,7 @@ import Distribution.Compat.Prelude import Distribution.Types.Version import Prelude () +import Distribution.CabalSpecVersion import Distribution.Parsec.Class import Distribution.Pretty import Distribution.Text @@ -417,7 +418,7 @@ instance Parsec VersionRange where prim = do op <- P.munch1 (`elem` "<>=^-") P.<?> "operator" case op of - "-" -> anyVersion <$ P.string "any" <|> noVersion <$ P.string "none" + "-" -> anyVersion <$ P.string "any" <|> P.string "none" *> noVersion' "==" -> do P.spaces @@ -432,11 +433,44 @@ instance Parsec VersionRange where case op of ">=" -> pure $ orLaterVersion v "<" -> pure $ earlierVersion v - "^>=" -> pure $ majorBoundVersion v + "^>=" -> majorBoundVersion' v "<=" -> pure $ orEarlierVersion v ">" -> pure $ laterVersion v _ -> fail $ "Unknown version operator " ++ show op + -- Note: There are other features: + -- && and || since 1.8 + -- x.y.* (wildcard) since 1.6 + + -- -none version range is available since 1.22 + noVersion' = do + csv <- askCabalSpecVersion + if csv >= CabalSpecV1_22 + then pure noVersion + else fail $ unwords + [ "-none version range used." + , "To use this syntax the package needs to specify at least 'cabal-version: 1.22'." + , "Alternatively, if broader compatibility is important then use" + , "<0 or other empty range." + ] + + -- ^>= is available since 2.0 + majorBoundVersion' v = do + csv <- askCabalSpecVersion + if csv >= CabalSpecV2_0 + then pure $ majorBoundVersion v + else fail $ unwords + [ "major bounded version syntax (caret, ^>=) used." + , "To use this syntax the package need to specify at least 'cabal-version: 2.0'." + , "Alternatively, if broader compatibility is important then use:" + , prettyShow $ eliminateMajorBoundSyntax $ majorBoundVersion v + ] + where + eliminateMajorBoundSyntax = hyloVersionRange embed projectVersionRange + embed (MajorBoundVersionF u) = intersectVersionRanges + (orLaterVersion u) (earlierVersion (majorUpperBound u)) + embed vr = embedVersionRange vr + -- either wildcard or normal version verOrWild :: CabalParsing m => m (Bool, Version) verOrWild = do diff --git a/Cabal/tests/ParserTests.hs b/Cabal/tests/ParserTests.hs index 46a3509e92f0e011604115e5094c5583e0e5fd52..c2be94946617a98c25b57b08dcb13655d3d32508 100644 --- a/Cabal/tests/ParserTests.hs +++ b/Cabal/tests/ParserTests.hs @@ -101,6 +101,8 @@ errorTests = testGroup "errors" , errorTest "forward-compat3.cabal" , errorTest "issue-5055.cabal" , errorTest "issue-5055-2.cabal" + , errorTest "noVersion.cabal" + , errorTest "noVersion2.cabal" ] errorTest :: FilePath -> TestTree @@ -139,6 +141,7 @@ regressionTests = testGroup "regressions" , regressionTest "wl-pprint-indef.cabal" , regressionTest "th-lift-instances.cabal" , regressionTest "issue-5055.cabal" + , regressionTest "noVersion.cabal" ] regressionTest :: FilePath -> TestTree diff --git a/Cabal/tests/ParserTests/errors/noVersion.cabal b/Cabal/tests/ParserTests/errors/noVersion.cabal new file mode 100644 index 0000000000000000000000000000000000000000..f6e1311b8f996d7436d88ebb724b32dbcbe3b743 --- /dev/null +++ b/Cabal/tests/ParserTests/errors/noVersion.cabal @@ -0,0 +1,10 @@ +name: noVersion +version: 0 +synopsis: -none in build-depends +build-type: Simple +cabal-version: 1.20 + +library + default-language: Haskell2010 + exposed-modules: ElseIf + build-depends: bad-package -none diff --git a/Cabal/tests/ParserTests/errors/noVersion.errors b/Cabal/tests/ParserTests/errors/noVersion.errors new file mode 100644 index 0000000000000000000000000000000000000000..ac3f225a79a4e9b4d1db7981f276a3bad88d69f9 --- /dev/null +++ b/Cabal/tests/ParserTests/errors/noVersion.errors @@ -0,0 +1,6 @@ +VERSION: Just (mkVersion [1,20]) +noVersion.cabal:10:38: +unexpected -none version range used. To use this syntax the package needs to specify at least 'cabal-version: 1.22'. Alternatively, if broader compatibility is important then use <0 or other empty range. + +bad-package -none + diff --git a/Cabal/tests/ParserTests/errors/noVersion2.cabal b/Cabal/tests/ParserTests/errors/noVersion2.cabal new file mode 100644 index 0000000000000000000000000000000000000000..d31c5dd48df759355367554f4f28c21e83a469f7 --- /dev/null +++ b/Cabal/tests/ParserTests/errors/noVersion2.cabal @@ -0,0 +1,10 @@ +name: noVersion +version: 0 +synopsis: ^>= in build-depends +build-type: Simple +cabal-version: 1.20 + +library + default-language: Haskell2010 + exposed-modules: ElseIf + build-depends: bad-package ^>= 2.0 diff --git a/Cabal/tests/ParserTests/errors/noVersion2.errors b/Cabal/tests/ParserTests/errors/noVersion2.errors new file mode 100644 index 0000000000000000000000000000000000000000..26415c85a7ae0fa5aa77519d1f2b99d9222f6fc2 --- /dev/null +++ b/Cabal/tests/ParserTests/errors/noVersion2.errors @@ -0,0 +1,7 @@ +VERSION: Just (mkVersion [1,20]) +noVersion2.cabal:10:40: +unexpected major bounded version syntax (caret, ^>=) used. To use this syntax the package need to specify at least 'cabal-version: 2.0'. Alternatively, if broader compatibility is important then use: >=2.0 && <2.1 +expecting "." or "-" + +bad-package ^>= 2.0 + diff --git a/Cabal/tests/ParserTests/regressions/haddock-api-2.18.1-check.check b/Cabal/tests/ParserTests/regressions/haddock-api-2.18.1-check.check index b9d2e11cbcbf41b68398522a3130c7926e4fed23..4d328b123ba1346b286200c0d92b63c3a30d6922 100644 --- a/Cabal/tests/ParserTests/regressions/haddock-api-2.18.1-check.check +++ b/Cabal/tests/ParserTests/regressions/haddock-api-2.18.1-check.check @@ -1,2 +1,11 @@ -'ghc-options: -O2' is rarely needed. Check that it is giving a real benefit and not just imposing longer compile times on your users. -The package uses major bounded version syntax in the 'build-depends' field: base ^>=4.10.0, Cabal ^>=2.0.0, ghc ^>=8.2, ghc-paths ^>=0.1.0.9, xhtml ^>=3000.2.2, QuickCheck ^>=2.10, hspec ^>=2.4.4, ghc ^>=8.2. To use this new syntax the package need to specify at least 'cabal-version: >= 2.0'. Alternatively, if broader compatibility is important then use: base >=4.10.0 && <4.11, Cabal >=2.0.0 && <2.1, ghc >=8.2 && <8.3, ghc-paths >=0.1.0.9 && <0.2, xhtml >=3000.2.2 && <3000.3, QuickCheck >=2.10 && <2.11, hspec >=2.4.4 && <2.5, ghc >=8.2 && <8.3 +ERROR: haddock-api-2.18.1-check.cabal:41:44: +unexpected major bounded version syntax (caret, ^>=) used. To use this syntax the package need to specify at least 'cabal-version: 2.0'. Alternatively, if broader compatibility is important then use: >=4.10.0 && <4.11 +expecting "." or "-" + +base ^>= 4.10.0 +, Cabal ^>= 2.0.0 +, ghc ^>= 8.2 +, ghc-paths ^>= 0.1.0.9 +, haddock-library == 1.4.4.* +, xhtml ^>= 3000.2.2 + diff --git a/Cabal/tests/ParserTests/regressions/noVersion.cabal b/Cabal/tests/ParserTests/regressions/noVersion.cabal new file mode 100644 index 0000000000000000000000000000000000000000..d643c06b052eb44ae5a3cec36d8d7bd7cb0cc5ab --- /dev/null +++ b/Cabal/tests/ParserTests/regressions/noVersion.cabal @@ -0,0 +1,11 @@ +name: noVersion +version: 0 +synopsis: -none in build-depends +build-type: Simple +cabal-version: 1.22 + +library + default-language: Haskell2010 + exposed-modules: ElseIf + + build-depends: bad-package -none diff --git a/Cabal/tests/ParserTests/regressions/noVersion.expr b/Cabal/tests/ParserTests/regressions/noVersion.expr new file mode 100644 index 0000000000000000000000000000000000000000..588e14bb95e6be100f2a5c4e25dde04b13fb2a4c --- /dev/null +++ b/Cabal/tests/ParserTests/regressions/noVersion.expr @@ -0,0 +1,103 @@ +GenericPackageDescription + {condBenchmarks = [], + condExecutables = [], + condForeignLibs = [], + condLibrary = Just + CondNode + {condTreeComponents = [], + condTreeConstraints = [Dependency + `PackageName "bad-package"` + (IntersectVersionRanges + (LaterVersion `mkVersion [1]`) + (EarlierVersion `mkVersion [1]`))], + condTreeData = Library + {exposedModules = [`ModuleName ["ElseIf"]`], + libBuildInfo = BuildInfo + {asmOptions = [], + asmSources = [], + autogenModules = [], + buildToolDepends = [], + buildTools = [], + buildable = True, + cSources = [], + ccOptions = [], + cmmOptions = [], + cmmSources = [], + cppOptions = [], + customFieldsBI = [], + cxxOptions = [], + cxxSources = [], + defaultExtensions = [], + defaultLanguage = Just Haskell2010, + extraBundledLibs = [], + extraFrameworkDirs = [], + extraGHCiLibs = [], + extraLibDirs = [], + extraLibFlavours = [], + extraLibs = [], + frameworks = [], + hsSourceDirs = [], + includeDirs = [], + includes = [], + installIncludes = [], + jsSources = [], + ldOptions = [], + mixins = [], + oldExtensions = [], + options = [], + otherExtensions = [], + otherLanguages = [], + otherModules = [], + pkgconfigDepends = [], + profOptions = [], + sharedOptions = [], + staticOptions = [], + targetBuildDepends = [Dependency + `PackageName "bad-package"` + (IntersectVersionRanges + (LaterVersion + `mkVersion [1]`) + (EarlierVersion + `mkVersion [1]`))], + virtualModules = []}, + libExposed = True, + libName = Nothing, + reexportedModules = [], + signatures = []}}, + condSubLibraries = [], + condTestSuites = [], + genPackageFlags = [], + packageDescription = PackageDescription + {author = "", + benchmarks = [], + bugReports = "", + buildDepends = [], + buildTypeRaw = Just Simple, + category = "", + copyright = "", + customFieldsPD = [], + dataDir = "", + dataFiles = [], + description = "", + executables = [], + extraDocFiles = [], + extraSrcFiles = [], + extraTmpFiles = [], + foreignLibs = [], + homepage = "", + library = Nothing, + licenseFiles = [], + licenseRaw = Left NONE, + maintainer = "", + package = PackageIdentifier + {pkgName = `PackageName "noVersion"`, + pkgVersion = `mkVersion [0]`}, + pkgUrl = "", + setupBuildInfo = Nothing, + sourceRepos = [], + specVersionRaw = Left `mkVersion [1,22]`, + stability = "", + subLibraries = [], + synopsis = "-none in build-depends", + testSuites = [], + testedWith = []}} diff --git a/Cabal/tests/ParserTests/regressions/noVersion.format b/Cabal/tests/ParserTests/regressions/noVersion.format new file mode 100644 index 0000000000000000000000000000000000000000..3aacd6b5f3bc4de5469f39aa993f2f923ed26965 --- /dev/null +++ b/Cabal/tests/ParserTests/regressions/noVersion.format @@ -0,0 +1,12 @@ +cabal-version: 1.22 +name: noVersion +version: 0 +synopsis: -none in build-depends +build-type: Simple + +library + exposed-modules: + ElseIf + default-language: Haskell2010 + build-depends: + bad-package >1 && <1