Skip to content

Commit

Permalink
Add check for upper bound on any package
Browse files Browse the repository at this point in the history
fixes #8291
presumably this will make it nag at anyone for forgetting
to add upper bounds to their packages.

add changelog

(presumably)

wait what?

move toDependencyVersionsMap to utils section

add nicer error message

simplify checking logic, add more comments

only emit missing upper bounds if bigger then one

don't add bound to internal libraries

filter out self from the dependency map

I think this is an external library so it needs an upper bound now?

add test for multilib

fix test suite by ignoring the warning

... probably not the best approach

change link to pvp instead of parsonsmatt

better wording on missing upper bound error

remove spurious parenthesis

change map creation from monad to list comprehension

use foldmap to get rid of maybe, fix compile error

rewrite from do notation to list comprehension

fix test suite failing
  • Loading branch information
jappeace committed Aug 24, 2022
1 parent e1f5d8b commit 826335b
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 32 deletions.
1 change: 1 addition & 0 deletions Cabal-tests/tests/CheckTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ checkTests = testGroup "regressions"
, checkTest "assoc-cpp-options.cabal"
, checkTest "public-multilib-1.cabal"
, checkTest "public-multilib-2.cabal"
, checkTest "public-multilib-3.cabal"
, checkTest "issue-6288-a.cabal"
, checkTest "issue-6288-b.cabal"
, checkTest "issue-6288-c.cabal"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ library
default-language: Haskell2010
build-depends:
, base ^>=4.14
, somelib:internal
, somelib:internal ^>=1.0

exposed-modules: Foo
14 changes: 14 additions & 0 deletions Cabal-tests/tests/ParserTests/regressions/public-multilib-3.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cabal-version: 3.0
name: public-multilib3
version: 0
synopsis: public-multilibs
category: Tests
license: MIT

library
default-language: Haskell2010
build-depends:
, base ^>=4.14
, somelib

exposed-modules: Foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
No 'maintainer' field.
No 'description' field.
These packages miss upper bounds 'somelib' please add them using `cabal gen-bounds` for suggestions. For more information see: https://pvp.haskell.org/
69 changes: 39 additions & 30 deletions Cabal/src/Distribution/PackageDescription/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ data CheckExplanation =
| UnknownArch [String]
| UnknownCompiler [String]
| BaseNoUpperBounds
| MissingUpperBounds [PackageName]
| SuspiciousFlagName [String]
| DeclaredUsedFlags (Set FlagName) (Set FlagName)
| NonASCIICustomField [String]
Expand Down Expand Up @@ -669,6 +670,12 @@ ppExplanation (UnknownArch unknownArches) =
"Unknown architecture name " ++ commaSep (map quote unknownArches)
ppExplanation (UnknownCompiler unknownImpls) =
"Unknown compiler name " ++ commaSep (map quote unknownImpls)
ppExplanation (MissingUpperBounds names) =
"These packages miss upper bounds '"
++ (intercalate "','" (unPackageName <$> names)) ++ "'"
++ " please add them using `cabal gen-bounds` for suggestions."
++ " For more information see: "
++ " https://pvp.haskell.org/"
ppExplanation BaseNoUpperBounds =
"The dependency 'build-depends: base' does not specify an upper "
++ "bound on the version number. Each major release of the 'base' "
Expand Down Expand Up @@ -1814,29 +1821,20 @@ checkCabalVersion pkg =
--
checkPackageVersions :: GenericPackageDescription -> [PackageCheck]
checkPackageVersions pkg =
catMaybes [

-- Check that the version of base is bounded above.
-- For example this bans "build-depends: base >= 3".
-- It should probably be "build-depends: base >= 3 && < 4"
-- which is the same as "build-depends: base == 3.*"
check (not (hasUpperBound baseDependency)) $
PackageDistInexcusable BaseNoUpperBounds

]
if length others > 0
then
PackageDistSuspiciousWarn (MissingUpperBounds others) : baseErrors
else
baseErrors
where
baseDependency = case typicalPkg pkg of
Right (pkg', _) | not (null baseDeps) ->
foldr intersectVersionRanges anyVersion baseDeps
where
baseDeps =
[ vr | Dependency pname vr _ <- allBuildDepends pkg'
, pname == mkPackageName "base" ]

-- Just in case finalizePD fails for any reason,
-- or if the package doesn't depend on the base package at all,
-- then we will just skip the check, since hasUpperBound noVersion = True
_ -> noVersion
baseErrors = PackageDistInexcusable BaseNoUpperBounds <$ bases
deps = toDependencyVersionsMap allBuildDepends pkg
-- base gets special treatment (it's more critical)
(bases, others) = partition (("base" ==) . unPackageName) $
[ name
| (name, vr) <- Map.toList deps
, not hasUpperBound vr
]

checkConditionals :: GenericPackageDescription -> [PackageCheck]
checkConditionals pkg =
Expand Down Expand Up @@ -2410,14 +2408,7 @@ checkSetupVersions pkg =
]
where
criticalPkgs = ["Cabal", "base"]
deps = case typicalPkg pkg of
Right (pkgs', _) ->
Map.fromListWith intersectVersionRanges
[ (pname, vr)
| sbi <- maybeToList $ setupBuildInfo pkgs'
, Dependency pname vr _ <- setupDepends sbi
]
_ -> Map.empty
deps = toDependencyVersionsMap (foldMap setupDepends . setupBuildInfo) pkg
emitError nm =
PackageDistInexcusable (UpperBoundSetup nm)

Expand Down Expand Up @@ -2456,6 +2447,24 @@ checkDuplicateModules pkg =
-- * Utils
-- ------------------------------------------------------------

toDependencyVersionsMap :: (PackageDescription -> [Dependency]) -> GenericPackageDescription -> Map PackageName VersionRange
toDependencyVersionsMap selectDependencies pkg = case typicalPkg pkg of
Right (pkgs', _) ->
let
self :: PackageName
self = pkgName $ package pkgs'
in
Map.fromListWith intersectVersionRanges $
[ (pname, vr)
| Dependency pname vr _ <- selectDependencies pkgs'
, pname /= self
]
-- Just in case finalizePD fails for any reason,
-- or if the package doesn't depend on the base package at all,
-- no deps is no checks.
_ -> Map.empty


quote :: String -> String
quote s = "'" ++ s ++ "'"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ exAvSrcPkg ex =
-- solver allows unknown extensions/languages when the compiler
-- supports them.
let checks = C.checkPackage (srcpkgDescription package) Nothing
in filter (not . isUnknownLangExt) checks
in filter (not . isMissingUpperBound) $ filter (not . isUnknownLangExt) checks
in if null pkgCheckErrors
then package
else error $ "invalid GenericPackageDescription for package "
Expand Down Expand Up @@ -671,6 +671,10 @@ exAvSrcPkg ex =
C.UnknownExtensions {} -> True
C.UnknownLanguages {} -> True
_ -> False
isMissingUpperBound :: C.PackageCheck -> Bool
isMissingUpperBound pc = case C.explanation pc of
C.MissingUpperBounds {} -> True
_ -> False


mkSimpleVersion :: ExamplePkgVersion -> C.Version
Expand Down
4 changes: 4 additions & 0 deletions changelog.d/pr-8339
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
synopsis: Add check for upper bound on any dependency in cabal check
report, list, init, fetch, info, upload, get.
prs: #8339
issues: #8291

0 comments on commit 826335b

Please sign in to comment.