Skip to content

Commit 8a3d979

Browse files
committed
Cabal 3.4: CabalSpecVersion (#1016)
The `cabal-version` field now gets parsed into an enum type, `CabalSpecVersion`, rather than `Version` (`Int` list). Some of the checks in `D.Server.Packages.Unpack.specVersionChecks` seem non-sensical now or outdated (do not mention cabal version 3 or higher). In this patch, I just mechanically ported this code to `CabalSpecVersion`, needs review.
1 parent 1ec6fcf commit 8a3d979

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

src/Distribution/Server/Packages/Index.hs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
{-# LANGUAGE BangPatterns, TemplateHaskell #-}
1+
{-# LANGUAGE BangPatterns #-}
2+
{-# LANGUAGE PatternSynonyms #-} -- for importing constructors
3+
{-# LANGUAGE TemplateHaskell #-}
4+
25
module Distribution.Server.Packages.Index (
36
writeIncremental,
47
TarIndexEntry(..),
@@ -30,7 +33,8 @@ import Distribution.Text
3033
import Distribution.Types.PackageName
3134
import Distribution.Package
3235
( Package, PackageId, packageName, packageVersion )
33-
import Distribution.Version (mkVersion)
36+
import Distribution.CabalSpecVersion
37+
( pattern CabalSpecV2_0 )
3438
import Data.Time.Clock
3539
( UTCTime )
3640
import Data.Time.Clock.POSIX
@@ -218,7 +222,7 @@ writeLegacyAux externalPackageRep updateEntry extras =
218222
where
219223
-- entry :: pkg -> Maybe Tar.Entry
220224
entry pkg
221-
| specVer >= mkVersion [2] = Nothing
225+
| specVerGEq2 = Nothing
222226
| otherwise = Just
223227
. updateEntry pkg
224228
. Tar.fileEntry tarPath
@@ -230,5 +234,5 @@ writeLegacyAux externalPackageRep updateEntry extras =
230234
</> name <.> "cabal"
231235

232236
-- TODO: Hack-alert! We want to do this in a more elegant way.
233-
specVer = parseSpecVerLazy cabalText
237+
specVerGEq2 = maybe False (>= CabalSpecV2_0) $ parseSpecVerLazy cabalText
234238
cabalText = externalPackageRep pkg

src/Distribution/Server/Packages/Unpack.hs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import qualified Codec.Archive.Tar as Tar
1717
import qualified Codec.Archive.Tar.Entry as Tar
1818
import qualified Codec.Archive.Tar.Check as Tar
1919

20+
import Distribution.CabalSpecVersion
21+
( CabalSpecVersion(..), showCabalSpecVersion )
2022
import Distribution.Version
21-
( Version, nullVersion, mkVersion )
23+
( nullVersion )
2224
import Distribution.Types.PackageName
2325
( mkPackageName, unPackageName )
2426
import Distribution.Package
@@ -196,30 +198,34 @@ basicChecks pkgid tarIndex = do
196198
-- special meaning in cabal's UI
197199
reservedPkgNames = map mkPackageName ["all","any","none","setup","lib","exe","test"]
198200

199-
specVersionChecks :: MonadError String m => Bool -> Version -> m ()
201+
specVersionChecks :: MonadError String m => Bool -> CabalSpecVersion -> m ()
200202
specVersionChecks specVerOk specVer = do
201-
when (not specVerOk || specVer < mkVersion [1]) $
203+
when (not specVerOk) $
202204
throwError "The 'cabal-version' field could not be properly parsed."
203205

204206
-- Don't allowing uploading new pre-1.2 .cabal files as the parser is likely too lax
205207
-- TODO: slowly phase out ancient cabal spec versions below 1.10
206-
when (specVer < mkVersion [1,2]) $
208+
when (specVer < CabalSpecV1_2) $
207209
throwError "'cabal-version' must be at least 1.2"
208210

209-
-- Reject not well-defined cabal spec versions on upload
210-
when (specVer >= mkVersion [1,25] && specVer < mkVersion [2]) $
211-
throwError "'cabal-version' in unassigned >=1.25 && <2 range; use 'cabal-version: 2.0' instead"
212-
213211
-- Safeguard; should already be caught by parser
214-
unless (specVer < mkVersion [2,5]) $
215-
throwError "'cabal-version' must be lower than 2.5"
212+
unless (specVer <= CabalSpecV2_4) $
213+
throwError "'cabal-version' must be at most 2.4"
216214

217215
-- Check whether a known spec version had been used
218216
-- TODO: move this into lib:Cabal
219-
let knownSpecVersions = map mkVersion [ [1,18], [1,20], [1,22], [1,24], [2,0], [2,2], [2,4] ]
220-
when (specVer >= mkVersion [1,18] && (specVer `notElem` knownSpecVersions)) $
217+
let knownSpecVersions =
218+
[ CabalSpecV1_18
219+
, CabalSpecV1_20
220+
, CabalSpecV1_22
221+
, CabalSpecV1_24
222+
, CabalSpecV2_0
223+
, CabalSpecV2_2
224+
, CabalSpecV2_4
225+
]
226+
when (specVer >= CabalSpecV1_18 && (specVer `notElem` knownSpecVersions)) $
221227
throwError ("'cabal-version' refers to an unreleased/unknown cabal specification version "
222-
++ display specVer ++ "; for a list of valid specification versions please consult "
228+
++ showCabalSpecVersion specVer ++ "; for a list of valid specification versions please consult "
223229
++ "https://www.haskell.org/cabal/users-guide/file-format-changelog.html")
224230

225231
-- | The issue is that browsers can upload the file name using either unix

src/Distribution/Server/Util/ParseSpecVer.hs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import qualified Data.ByteString.Lazy as BSL
1919
import qualified Data.ByteString.Lazy.Char8 as BC8L
2020
import Data.List.NonEmpty ( toList)
2121
import Distribution.Text
22+
import Distribution.CabalSpecVersion
2223
import Distribution.Pretty ( prettyShow )
2324
import Distribution.Parsec ( PWarning, PError )
2425
import Distribution.Version
@@ -45,22 +46,25 @@ import Distribution.PackageDescription.Parsec ( runParseResult, parseG
4546
-- inferred 'specVersion'. IOW, Hackage ensures on upload that only
4647
-- @.cabal@ files are accepted which support the heuristic parsing.
4748
--
48-
-- If no valid version field can be found, @mkVersion [0]@ is returned.
49-
parseSpecVer :: ByteString -> Version
50-
parseSpecVer = maybe (mkVersion [0]) id . findCabVer
49+
-- If no valid version field can be found, @Nothing@ is returned.
50+
parseSpecVer :: ByteString -> Maybe CabalSpecVersion
51+
parseSpecVer = findCabVer
5152

52-
parseSpecVerLazy :: BSL.ByteString -> Version
53+
parseSpecVerLazy :: BSL.ByteString -> Maybe CabalSpecVersion
5354
parseSpecVerLazy = parseSpecVer . BSL.toStrict
5455

56+
versionToCabalSpecVersion :: Version -> Maybe CabalSpecVersion
57+
versionToCabalSpecVersion = cabalSpecFromVersionDigits . versionNumbers
58+
5559
isWS :: Word8 -> Bool
5660
isWS = (`elem` [0x20,0x09])
5761

5862
eatWS :: ByteString -> ByteString
5963
eatWS = BS.dropWhile isWS
6064

6165
-- | Try to heuristically locate & parse a 'cabal-version' field
62-
findCabVer :: ByteString -> Maybe Version
63-
findCabVer raw = msum [ decodeVer y | (_,_,y) <- findCabVers raw ]
66+
findCabVer :: ByteString -> Maybe CabalSpecVersion
67+
findCabVer raw = msum [ versionToCabalSpecVersion =<< decodeVer y | (_,_,y) <- findCabVers raw ]
6468

6569
-- | Return list of @cabal-version@ candidates as 3-tuples of
6670
-- (prefix,indentation-level,value-words) in reverse order of
@@ -282,16 +286,17 @@ scanSpecVersionLazy bs = do
282286
-- * Starting with cabal-version:2.2 'scanSpecVersionLazy' must succeed
283287
--
284288
-- 'True' is returned in the first element if sanity checks passes.
285-
parseGenericPackageDescriptionChecked :: BSL.ByteString -> (Bool,[PWarning], Either (Maybe Version, [PError]) GenericPackageDescription)
289+
parseGenericPackageDescriptionChecked :: BSL.ByteString -> (Bool, [PWarning], Either (Maybe Version, [PError]) GenericPackageDescription)
286290
parseGenericPackageDescriptionChecked bs = case parseGenericPackageDescription' bs of
287291
(warns, Left pe) -> (False, warns, Left $ fmap toList pe)
288-
(warns, Right gpd) -> (isOk (specVersion (packageDescription gpd)),warns, Right gpd)
292+
(warns, Right gpd) -> (isOk (specVersion (packageDescription gpd)), warns, Right gpd)
289293
where
290-
isOk :: Version -> Bool
294+
isOk :: CabalSpecVersion -> Bool
291295
isOk v
292-
| v /= parseSpecVerLazy bs = False
293-
| Just v' <- scanSpecVersionLazy bs = v == v'
294-
| otherwise = v < mkVersion [2,3]
296+
| Just v /= parseSpecVerLazy bs = False
297+
| Just v' <- versionToCabalSpecVersion =<< scanSpecVersionLazy bs
298+
= v == v'
299+
| otherwise = v <= CabalSpecV2_2
295300

296301
#if defined(MIN_VERSION_cabal_parsers)
297302
parseGenericPackageDescription' bs' = compatParseGenericPackageDescription (BSL.toStrict bs')

tests/PackageTestMain.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ badSpecVer =
7878
Left err ->
7979
HUnit.assertBool
8080
("Error found, but not about invalid spec version: " ++ err)
81-
("cabal-version" `isInfixOf` err)
81+
("cabal spec version" `isInfixOf` err)
8282

8383
-- | Some tar files in hackage are missing directory entries.
8484
-- Ensure that they can be verified even without the directory entries.

0 commit comments

Comments
 (0)