Skip to content

Commit b101f2d

Browse files
ffaf1mergify[bot]
andauthored
Make check comply with Hackage requirements (#8897)
* Abstract `isDistError` There are two places in cabal codebase where `isDistError` is defined (would Hackage refuse the package based on this error?), plus another one in hackage-server (src/Distribution/Server/Packages/Unpack.hs). This commit refactors the definitions into a singel `isHackageDistError` (in Distribution.Client.Check) so everything is in sync. The function is exported, for the benefit of third-party tools. * Make `check` comply with Hackage requirements `cabal check` exits with 0 or 1. As now the `1` exit is slightly stricter than “Hackage would reject this”, as even PackageDistSuspicious errors will trigger a `1` exit. This patch rectifies this and also specifies the behaviour in the documentation. Notice the usage of “should” and “will”: we cannot be sure Hackage will accept a package (e.g.: maybe there are name clashes) but there are no type I errors: if it fails `cabal check`, Hackage will refuse it. * Make testsuite pass All the modified tests returned 1 on exit, now they return 0. * Add changelog for #8897 * Expand catchall into constructors (Andreas’ review) For `isHackageDistError`, so that in the future, when constructors are added, the compiler will warn about missing them missing and a thoughtful choice will be made. * Use LambdaCase (Artem’s review) Saves typing `isHackageDistError` four times more. * Reword help strings (Artem’s review) Make clear that errors will make `check` return 1. * Fix typo --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 3cb3ffb commit b101f2d

File tree

28 files changed

+59
-37
lines changed

28 files changed

+59
-37
lines changed

Cabal/src/Distribution/PackageDescription/Check.hs

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE LambdaCase #-}
2+
13
-----------------------------------------------------------------------------
24
-- |
35
-- Module : Distribution.PackageDescription.Check
@@ -28,6 +30,7 @@ module Distribution.PackageDescription.Check (
2830
checkConfiguredPackage,
2931
wrapParseWarning,
3032
ppPackageCheck,
33+
isHackageDistError,
3134

3235
-- ** Checking package contents
3336
checkPackageFiles,
@@ -846,6 +849,15 @@ data PackageCheck =
846849
| PackageDistInexcusable { explanation :: CheckExplanation }
847850
deriving (Eq, Ord)
848851

852+
-- | Would Hackage refuse a package because of this error?
853+
isHackageDistError :: PackageCheck -> Bool
854+
isHackageDistError = \case
855+
(PackageBuildImpossible {}) -> True
856+
(PackageBuildWarning {}) -> True
857+
(PackageDistInexcusable {}) -> True
858+
(PackageDistSuspicious {}) -> False
859+
(PackageDistSuspiciousWarn {}) -> False
860+
849861
-- | Pretty printing 'PackageCheck'.
850862
--
851863
ppPackageCheck :: PackageCheck -> String

Cabal/src/Distribution/Simple/SrcDist.hs

+1-4
Original file line numberDiff line numberDiff line change
@@ -501,10 +501,7 @@ printPackageProblems :: Verbosity -> PackageDescription -> IO ()
501501
printPackageProblems verbosity pkg_descr = do
502502
ioChecks <- checkPackageFiles verbosity pkg_descr "."
503503
let pureChecks = checkConfiguredPackage pkg_descr
504-
isDistError (PackageDistSuspicious _) = False
505-
isDistError (PackageDistSuspiciousWarn _) = False
506-
isDistError _ = True
507-
(errors, warnings) = partition isDistError (pureChecks ++ ioChecks)
504+
(errors, warnings) = partition isHackageDistError (pureChecks ++ ioChecks)
508505
unless (null errors) $
509506
notice verbosity $ "Distribution quality errors:\n"
510507
++ unlines (map ppPackageCheck errors)

cabal-install/src/Distribution/Client/Check.hs

+5-8
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ readGenericPackageDescriptionCheck verbosity fpath = do
4848
die' verbosity "parse error"
4949
Right x -> return (warnings, x)
5050

51-
-- | Note: must be called with the CWD set to the directory containing
51+
-- | Checks a packge for common errors. Returns @True@ if the package
52+
-- is fit to upload to Hackage, @False@ otherwise.
53+
-- Note: must be called with the CWD set to the directory containing
5254
-- the '.cabal' file.
5355
check :: Verbosity -> IO Bool
5456
check verbosity = do
@@ -94,20 +96,15 @@ check verbosity = do
9496
warn verbosity "The following errors will cause portability problems on other environments:"
9597
printCheckMessages distInexusable
9698

97-
let isDistError (PackageDistSuspicious {}) = False
98-
isDistError (PackageDistSuspiciousWarn {}) = False
99-
isDistError _ = True
100-
isCheckError (PackageDistSuspiciousWarn {}) = False
101-
isCheckError _ = True
102-
errors = filter isDistError packageChecks
99+
let errors = filter isHackageDistError packageChecks
103100

104101
unless (null errors) $
105102
warn verbosity "Hackage would reject this package."
106103

107104
when (null packageChecks) $
108105
notice verbosity "No errors or warnings could be found in the package."
109106

110-
return (not . any isCheckError $ packageChecks)
107+
return (null errors)
111108

112109
where
113110
printCheckMessages :: [PackageCheck] -> IO ()

cabal-install/src/Distribution/Client/Setup.hs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1201,8 +1201,9 @@ checkCommand = CommandUI {
12011201
"Expects a .cabal package file in the current directory.\n"
12021202
++ "\n"
12031203
++ "The checks correspond to the requirements to packages on Hackage. "
1204-
++ "If no errors and warnings are reported, Hackage will accept this "
1205-
++ "package.\n",
1204+
++ "If no errors and warnings are reported, Hackage should accept the "
1205+
++ "package. If errors are present, `check` exits with 1 and Hackage "
1206+
++ "will refuse the package.\n",
12061207
commandNotes = Nothing,
12071208
commandUsage = usageFlags "check",
12081209
commandDefaultFlags = toFlag normal,

cabal-testsuite/PackageTests/Check/ConfiguredPackage/COptions/CxxOs/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `cxx-options`, do not use `-O1`.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/CabalVersion/DefaultExtension/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `default-extensions` need ≥1.10.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/CabalVersion/DefaultLanguage/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `default-language` need ≥1.10.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/CabalVersion/ExtraDynamicLibraryFlavour/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `extra-dynamic-library-flavour` need ≥3.0.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/CabalVersion/Mixins/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `mixins` need ≥2.0.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/CabalVersion/Sources/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `cmm-sources` and friends need ≥3.0.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/CabalVersion/VirtualModules/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `virtual-modules` need ≥2.2.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Fields/DeprecatedExtension/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Deprecated extension.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Fields/NoCategory/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- No category.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Fields/NoDescription/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- No description.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Fields/NoMaintainer/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- No maintainer.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Fields/NoSynopsis/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- No synopsis.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Fields/ShortDescription/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Description should be longer than synopsis.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/GHCOptions/GHCSharedOptions/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Tricky option in `ghc-shared-options`.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/License/NoFileSpecified/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `licence-file` missing.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/License/SuspiciousLicense/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Suspicious license BSD4.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/License/SuspiciousVersion/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Suspicious license version.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/License/WarnAllRightsReserved/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Dubious AllRightsReserved.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/ConfiguredPackage/Sanity/VersionSignatures/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- `signatures` field used with cabal-version < 2.0
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/NonConfCheck/DevOnlyFlags/Profiling/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Profiling flags unsuited for distribution.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/NonConfCheck/UnusedFlags/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Unused flag.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

cabal-testsuite/PackageTests/Check/PackageFiles/VCSInfo/cabal.test.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import Test.Cabal.Prelude
22

33
-- Missing VCS info.
44
main = cabalTest $
5-
fails $ cabal "check" []
5+
cabal "check" []

changelog.d/pr-8897

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
synopsis: Make check comply with Hackage requirements
2+
packages: Cabal cabal-install
3+
prs: #8897
4+
5+
description: {
6+
7+
- `cabal check` will only return exitcode 1 when the package is not fit
8+
for Hackage. E.g. it will not error anymore when your `synopsis:` is
9+
larger than `description:`, just emit a warning.
10+
- Cabal: Distribution.Client.Check now exports `isHackageDistError`, for
11+
third-party tools to know if a specific error will preclude a package
12+
from being uploaded to Hacakge.
13+
14+
}

doc/cabal-commands.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,8 @@ Run ``cabal check`` in the folder where your ``.cabal`` package file is.
977977
Set verbosity level (0–3, default is 1).
978978

979979
``cabal check`` mimics Hackage's requirements: if no error or warning
980-
is reported, Hackage should accept your package.
980+
is reported, Hackage should accept your package. If errors are present
981+
``cabal check`` exits with ``1`` and Hackage will refuse the package.
981982

982983
cabal sdist
983984
^^^^^^^^^^^

0 commit comments

Comments
 (0)