@@ -10,7 +10,6 @@ import Codec.Compression.GZip qualified as GZip
10
10
import Control.Monad (unless , void , when )
11
11
import Data.Aeson qualified as Aeson
12
12
import Data.Bifunctor (second )
13
- import Data.ByteString.Char8 qualified as BS
14
13
import Data.ByteString.Lazy.Char8 qualified as BL
15
14
import Data.List (sortOn )
16
15
import Data.List.NonEmpty qualified as NE
@@ -28,7 +27,7 @@ import Foliage.Meta
28
27
import Foliage.Meta.Aeson ()
29
28
import Foliage.Options
30
29
import Foliage.Pages
31
- import Foliage.PreparePackageVersion (PreparedPackageVersion (.. ), preparePackageVersion )
30
+ import Foliage.PreparePackageVersion (PreparedPackageVersion (.. ), Timestamped ( .. ), preparePackageVersion )
32
31
import Foliage.PrepareSdist (addPrepareSdistRule )
33
32
import Foliage.PrepareSource (addPrepareSourceRule )
34
33
import Foliage.RemoteAsset (addFetchRemoteAssetRule )
@@ -113,18 +112,14 @@ buildAction
113
112
114
113
cabalEntries <-
115
114
foldMap
116
- ( \ PreparedPackageVersion {pkgId, pkgTimestamp, originalCabalFilePath, cabalFileRevisions} -> do
115
+ ( \ PreparedPackageVersion {pkgId, pkgTimestamp, originalCabalFilePath, cabalFileRevisions} ->
117
116
-- original cabal file, with its timestamp (if specified)
118
117
let cabalFileTimestamp = fromMaybe currentTime pkgTimestamp
119
- cf <- prepareIndexPkgCabal pkgId cabalFileTimestamp originalCabalFilePath
120
-
121
- -- all revised cabal files, with their timestamp
122
- revcf <- for cabalFileRevisions $ uncurry (prepareIndexPkgCabal pkgId)
123
-
124
118
-- WARN: So far Foliage allows publishing a package and a cabal file revision with the same timestamp
125
119
-- This accidentally works because 1) the following inserts the original cabal file before the revisions
126
120
-- AND 2) Data.List.sortOn is stable. The revised cabal file will always be after the original one.
127
- return $ cf : revcf
121
+ in -- all revised cabal files, with their timestamp
122
+ prepareIndexPkgCabal pkgId (Timestamped cabalFileTimestamp originalCabalFilePath) (sortOn timestamp cabalFileRevisions)
128
123
)
129
124
packageVersions
130
125
@@ -138,9 +133,8 @@ buildAction
138
133
liftIO $ BL. writeFile path $ renderSignedJSON targetKeys targets
139
134
pure $
140
135
mkTarEntry
141
- (renderSignedJSON targetKeys targets)
136
+ (Timestamped (fromMaybe currentTime pkgTimestamp) ( renderSignedJSON targetKeys targets) )
142
137
(IndexPkgMetadata pkgId)
143
- (fromMaybe currentTime pkgTimestamp)
144
138
145
139
let extraEntries = getExtraEntries packageVersions
146
140
@@ -284,11 +278,29 @@ getPackageVersions inputDir = do
284
278
285
279
forP metaFiles $ preparePackageVersion inputDir
286
280
287
- prepareIndexPkgCabal :: PackageId -> UTCTime -> FilePath -> Action Tar. Entry
288
- prepareIndexPkgCabal pkgId timestamp filePath = do
289
- need [filePath]
290
- contents <- liftIO $ BS. readFile filePath
291
- pure $ mkTarEntry (BL. fromStrict contents) (IndexPkgCabal pkgId) timestamp
281
+ prepareIndexPkgCabal :: PackageId -> Timestamped FilePath -> [Timestamped FilePath ] -> Action [Tar. Entry ]
282
+ prepareIndexPkgCabal pkgId (Timestamped timestamp originalFilePath) revisions = do
283
+ need (originalFilePath : map timestampedValue revisions)
284
+ original <- liftIO (BL. readFile originalFilePath)
285
+ revisionsApplied <- applyRevisionsInOrder [Timestamped timestamp original] revisions
286
+ pure $ map (\ content -> mkTarEntry content (IndexPkgCabal pkgId)) revisionsApplied
287
+
288
+ applyRevisionsInOrder :: [Timestamped BL. ByteString ] -> [Timestamped FilePath ] -> Action [Timestamped BL. ByteString ]
289
+ applyRevisionsInOrder acc [] = pure (reverse acc)
290
+ applyRevisionsInOrder acc (patch : remainingPatches) = do
291
+ newContent <- applyRevision (timestampedValue $ last acc) patch
292
+ applyRevisionsInOrder (newContent : acc) remainingPatches
293
+
294
+ applyRevision :: BL. ByteString -> Timestamped FilePath -> Action (Timestamped BL. ByteString )
295
+ applyRevision lastRevisionContents (Timestamped timestamp revisionPath) = do
296
+ content <-
297
+ if takeExtension revisionPath `elem` [" .diff" , " .patch" ]
298
+ then do
299
+ liftIO $ putStrLn $ " Applying patch " ++ revisionPath
300
+ cmd_ (StdinBS lastRevisionContents) [" patch" , " -i" , revisionPath]
301
+ liftIO $ BL. readFile revisionPath
302
+ else pure lastRevisionContents
303
+ return $ Timestamped timestamp content
292
304
293
305
prepareIndexPkgMetadata :: Maybe UTCTime -> PreparedPackageVersion -> Action Targets
294
306
prepareIndexPkgMetadata expiryTime PreparedPackageVersion {pkgId, sdistPath} = do
@@ -324,7 +336,7 @@ getExtraEntries packageVersions =
324
336
effectiveRanges :: [(UTCTime , VersionRange )]
325
337
effectiveRanges = NE. tail $ NE. scanl applyChangeToRange (posixSecondsToUTCTime 0 , anyVersion) deprecationChanges
326
338
-- Create a `Tar.Entry` for the package group, its computed `VersionRange` and a timestamp.
327
- createTarEntry (ts, effectiveRange) = mkTarEntry (BL. pack $ prettyShow effectiveRange) (IndexPkgPrefs pn) ts
339
+ createTarEntry (ts, effectiveRange) = mkTarEntry (Timestamped ts ( BL. pack $ prettyShow effectiveRange)) (IndexPkgPrefs pn)
328
340
in foldMap generateEntriesForGroup groupedPackageVersions
329
341
330
342
-- TODO: the functions belows should be moved to Foliage.PreparedPackageVersion
@@ -351,8 +363,8 @@ applyDeprecation pkgVersion deprecated =
351
363
then intersectVersionRanges (notThisVersion pkgVersion)
352
364
else unionVersionRanges (thisVersion pkgVersion)
353
365
354
- mkTarEntry :: BL. ByteString -> IndexFile dec -> UTCTime -> Tar. Entry
355
- mkTarEntry contents indexFile timestamp =
366
+ mkTarEntry :: Timestamped BL. ByteString -> IndexFile dec -> Tar. Entry
367
+ mkTarEntry ( Timestamped timestamp contents) indexFile =
356
368
(Tar. fileEntry tarPath contents)
357
369
{ Tar. entryTime = floor $ Time. utcTimeToPOSIXSeconds timestamp,
358
370
Tar. entryOwnership =
0 commit comments