Merge pull request #37 from andreabedini/add-consistency-check

Add consistency check
This commit is contained in:
Andrea Bedini 2023-03-07 11:45:36 +08:00 committed by GitHub
commit 20049b1e81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 462 additions and 351 deletions

View File

@ -18,7 +18,7 @@ module Distribution.PackageDescription.FieldGrammar.Copy
where
import Distribution.CabalSpecVersion
import qualified Distribution.Compat.CharParsing as P
import Distribution.Compat.CharParsing qualified as P
import Distribution.Compat.Newtype (Newtype, pack', unpack')
import Distribution.Compat.Prelude
import Distribution.Compiler (CompilerFlavor (..))
@ -29,8 +29,8 @@ import Distribution.PackageDescription
import Distribution.PackageDescription.FieldGrammar hiding (packageDescriptionFieldGrammar)
import Distribution.Parsec
import Distribution.Pretty (Pretty (..), showToken)
import qualified Distribution.SPDX as SPDX
import qualified Distribution.Types.Lens as L
import Distribution.SPDX qualified as SPDX
import Distribution.Types.Lens qualified as L
import Distribution.Utils.Path
import Distribution.Version (Version, VersionRange)
import Prelude ()

View File

@ -2,14 +2,14 @@
module Distribution.Types.Orphans where
import Data.Aeson (ToJSON (toJSON))
import Development.Shake.Classes (Hashable)
import Distribution.Pretty (prettyShow)
import Distribution.Types.PackageId (PackageIdentifier)
import Distribution.Types.PackageName (PackageName)
import Distribution.Types.Version (Version)
import Distribution.Types.VersionRange (VersionRange)
import Distribution.Utils.ShortText (ShortText)
import Data.Aeson (ToJSON (toJSON))
import Distribution.Pretty (prettyShow)
instance ToJSON PackageIdentifier where
toJSON = toJSON . prettyShow

View File

@ -17,15 +17,15 @@ import Data.Traversable (for)
import Development.Shake
import Development.Shake.FilePath
import Distribution.Package
import Distribution.Parsec (simpleParsec)
import Distribution.Pretty (prettyShow)
import Foliage.HackageSecurity hiding (ToJSON, toJSON)
import Foliage.Meta
import Foliage.Meta.Aeson ()
import Foliage.Options
import Foliage.Pages
import Foliage.PrepareSdist
import Foliage.PrepareSource (addPrepareSourceRule, prepareSource)
import Foliage.PreparePackageVersion (PreparedPackageVersion (..), preparePackageVersion)
import Foliage.PrepareSdist (addPrepareSdistRule)
import Foliage.PrepareSource (addPrepareSourceRule)
import Foliage.RemoteAsset (addFetchRemoteAssetRule)
import Foliage.Shake
import Foliage.Time qualified as Time
@ -99,31 +99,21 @@ buildAction
when doWritePackageMeta $
makeMetadataFile outputDir packageVersions
void $ forP packageVersions $ makePackageVersionPage inputDir outputDir
void $ forP packageVersions $ makePackageVersionPage outputDir
void $ forP packageVersions $ \pkgMeta@PackageVersionMeta {pkgId} -> do
void $ forP packageVersions $ \PreparedPackageVersion {pkgId, cabalFilePath} -> do
let PackageIdentifier {pkgName, pkgVersion} = pkgId
cabalFilePath <- maybe (originalCabalFile pkgMeta) pure (revisedCabalFile inputDir pkgMeta)
copyFileChanged cabalFilePath (outputDir </> "index" </> prettyShow pkgName </> prettyShow pkgVersion </> prettyShow pkgName <.> "cabal")
cabalEntries <-
foldMap
( \pkgMeta@PackageVersionMeta {pkgId, pkgSpec} -> do
let PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions} = pkgSpec
( \PreparedPackageVersion {pkgId, pkgTimestamp, originalCabalFilePath, cabalFileRevisions} -> do
-- original cabal file, with its timestamp (if specified)
cabalFilePath <- originalCabalFile pkgMeta
let cabalFileTimestamp = fromMaybe currentTime packageVersionTimestamp
cf <- prepareIndexPkgCabal pkgId cabalFileTimestamp cabalFilePath
let cabalFileTimestamp = fromMaybe currentTime pkgTimestamp
cf <- prepareIndexPkgCabal pkgId cabalFileTimestamp originalCabalFilePath
-- all revised cabal files, with their timestamp
revcf <-
for packageVersionRevisions $
\RevisionSpec {revisionTimestamp, revisionNumber} ->
prepareIndexPkgCabal
pkgId
revisionTimestamp
(cabalFileRevisionPath inputDir pkgId revisionNumber)
revcf <- for cabalFileRevisions $ uncurry (prepareIndexPkgCabal pkgId)
return $ cf : revcf
)
@ -131,17 +121,16 @@ buildAction
targetKeys <- maybeReadKeysAt "target"
metadataEntries <-
forP packageVersions $ \pkg@PackageVersionMeta {pkgId, pkgSpec} -> do
forP packageVersions $ \ppv@PreparedPackageVersion {pkgId, pkgTimestamp} -> do
let PackageIdentifier {pkgName, pkgVersion} = pkgId
let PackageVersionSpec {packageVersionTimestamp} = pkgSpec
targets <- prepareIndexPkgMetadata expiryTime pkg
targets <- prepareIndexPkgMetadata expiryTime ppv
let path = outputDir </> "index" </> prettyShow pkgName </> prettyShow pkgVersion </> "package.json"
liftIO $ BL.writeFile path $ renderSignedJSON targetKeys targets
return $
pure $
mkTarEntry
(renderSignedJSON targetKeys targets)
(IndexPkgMetadata pkgId)
(fromMaybe currentTime packageVersionTimestamp)
(fromMaybe currentTime pkgTimestamp)
let tarContents = Tar.write $ sortOn Tar.entryTime (cabalEntries ++ metadataEntries)
traced "Writing index" $ do
@ -231,30 +220,27 @@ buildAction
timestampInfoSnapshot = snapshotInfo
}
makeMetadataFile :: FilePath -> [PackageVersionMeta] -> Action ()
makeMetadataFile :: FilePath -> [PreparedPackageVersion] -> Action ()
makeMetadataFile outputDir packageVersions = traced "writing metadata" $ do
createDirectoryIfMissing True (outputDir </> "foliage")
Aeson.encodeFile
(outputDir </> "foliage" </> "packages.json")
(map encodePackageVersionMeta packageVersions)
(map encodePackageVersion packageVersions)
where
encodePackageVersionMeta
PackageVersionMeta
encodePackageVersion
PreparedPackageVersion
{ pkgId = PackageIdentifier {pkgName, pkgVersion},
pkgSpec =
PackageVersionSpec
{ packageVersionSource,
packageVersionForce,
packageVersionTimestamp
}
pkgTimestamp,
pkgVersionForce,
pkgVersionSource
} =
Aeson.object
( [ "pkg-name" Aeson..= pkgName,
"pkg-version" Aeson..= pkgVersion,
"url" Aeson..= sourceUrl packageVersionSource
"url" Aeson..= sourceUrl pkgVersionSource
]
++ ["forced-version" Aeson..= True | packageVersionForce]
++ (case packageVersionTimestamp of Nothing -> []; Just t -> ["timestamp" Aeson..= t])
++ ["forced-version" Aeson..= True | pkgVersionForce]
++ (case pkgTimestamp of Nothing -> []; Just t -> ["timestamp" Aeson..= t])
)
sourceUrl :: PackageVersionSource -> URI
@ -272,58 +258,28 @@ makeMetadataFile outputDir packageVersions = traced "writing metadata" $ do
uriQuery = "?dir=" ++ subdir
}
getPackageVersions :: FilePath -> Action [PackageVersionMeta]
getPackageVersions :: FilePath -> Action [PreparedPackageVersion]
getPackageVersions inputDir = do
metaFiles <- getDirectoryFiles inputDir ["*/*/meta.toml"]
when (null metaFiles) $ do
putError $
error $
unlines
[ "We could not find any package metadata file (i.e. _sources/<name>/<version>/meta.toml)",
"Make sure you are passing the right input directory. The default input directory is _sources"
]
fail "no package metadata found"
forP metaFiles $ \metaFile -> do
let [pkgName, pkgVersion, _] = splitDirectories metaFile
let Just name = simpleParsec pkgName
let Just version = simpleParsec pkgVersion
let pkgId = PackageIdentifier name version
pkgSpec <-
readPackageVersionSpec' (inputDir </> metaFile) >>= \case
PackageVersionSpec {packageVersionRevisions, packageVersionTimestamp = Nothing}
| not (null packageVersionRevisions) -> do
putError $
unlines
[ inputDir </> metaFile <> " has cabal file revisions but the original package has no timestamp.",
"This combination doesn't make sense. Either add a timestamp on the original package or remove the revisions"
]
fail "invalid package metadata"
PackageVersionSpec {packageVersionRevisions, packageVersionTimestamp = Just pkgTs}
| any ((< pkgTs) . revisionTimestamp) packageVersionRevisions -> do
putError $
unlines
[ inputDir </> metaFile <> " has a revision with timestamp earlier than the package itself.",
"Adjust the timestamps so that all revisions come after the original package"
]
fail "invalid package metadata"
meta ->
return meta
return $ PackageVersionMeta pkgId pkgSpec
forP metaFiles $ preparePackageVersion inputDir
prepareIndexPkgCabal :: PackageId -> UTCTime -> FilePath -> Action Tar.Entry
prepareIndexPkgCabal pkgId timestamp filePath = do
need [filePath]
contents <- liftIO $ BS.readFile filePath
return $ mkTarEntry (BL.fromStrict contents) (IndexPkgCabal pkgId) timestamp
pure $ mkTarEntry (BL.fromStrict contents) (IndexPkgCabal pkgId) timestamp
prepareIndexPkgMetadata :: Maybe UTCTime -> PackageVersionMeta -> Action Targets
prepareIndexPkgMetadata expiryTime PackageVersionMeta {pkgId, pkgSpec} = do
srcDir <- prepareSource pkgId pkgSpec
sdist <- prepareSdist srcDir
targetFileInfo <- computeFileInfoSimple' sdist
prepareIndexPkgMetadata :: Maybe UTCTime -> PreparedPackageVersion -> Action Targets
prepareIndexPkgMetadata expiryTime PreparedPackageVersion {pkgId, sdistPath} = do
targetFileInfo <- computeFileInfoSimple' sdistPath
let packagePath = repoLayoutPkgTarGz hackageRepoLayout pkgId
return
Targets
@ -346,8 +302,11 @@ mkTarEntry contents indexFile timestamp =
}
}
where
tarPath = case Tar.toTarPath False indexPath of
Left e -> error $ "Invalid tar path " ++ indexPath ++ "(" ++ e ++ ")"
Right tp -> tp
indexPath = toFilePath $ castRoot $ indexFileToPath hackageIndexLayout indexFile
Right tarPath = Tar.toTarPath False indexPath
anchorPath :: Path Absolute -> (RepoLayout -> RepoPath) -> FilePath
anchorPath outputDirRoot p =

View File

@ -1,3 +1,5 @@
{-# LANGUAGE ViewPatterns #-}
module Foliage.CmdImportIndex
( cmdImportIndex,
)
@ -48,31 +50,31 @@ importIndex f (Tar.Next e es) m =
case isCabalFile e of
Just (pkgId, contents, time)
| f pkgId ->
do
putStrLn $ "Found cabal file " ++ prettyShow pkgId ++ " with timestamp " ++ show time
let -- new package
go Nothing =
pure $
Just $
PackageVersionSpec
{ packageVersionSource = TarballSource (pkgIdToHackageUrl pkgId) Nothing,
packageVersionTimestamp = Just time,
packageVersionRevisions = [],
packageVersionForce = False
}
-- Existing package, new revision
go (Just sm) = do
let revnum = 1 + fromMaybe 0 (latestRevisionNumber sm)
newRevision = RevisionSpec {revisionNumber = revnum, revisionTimestamp = time}
-- Repeatedly adding at the end of a list is bad performance but good for the moment.
let sm' = sm {packageVersionRevisions = packageVersionRevisions sm ++ [newRevision]}
let PackageIdentifier pkgName pkgVersion = pkgId
let outDir = "_sources" </> unPackageName pkgName </> prettyShow pkgVersion </> "revisions"
createDirectoryIfMissing True outDir
BSL.writeFile (outDir </> show revnum <.> "cabal") contents
return $ Just sm'
m' <- M.alterF go pkgId m
importIndex f es m'
do
putStrLn $ "Found cabal file " ++ prettyShow pkgId ++ " with timestamp " ++ show time
let -- new package
go Nothing =
pure $
Just $
PackageVersionSpec
{ packageVersionSource = TarballSource (pkgIdToHackageUrl pkgId) Nothing,
packageVersionTimestamp = Just time,
packageVersionRevisions = [],
packageVersionForce = False
}
-- Existing package, new revision
go (Just sm) = do
let revnum = 1 + fromMaybe 0 (latestRevisionNumber sm)
newRevision = RevisionSpec {revisionNumber = revnum, revisionTimestamp = time}
-- Repeatedly adding at the end of a list is bad performance but good for the moment.
let sm' = sm {packageVersionRevisions = packageVersionRevisions sm ++ [newRevision]}
let PackageIdentifier pkgName pkgVersion = pkgId
let outDir = "_sources" </> unPackageName pkgName </> prettyShow pkgVersion </> "revisions"
createDirectoryIfMissing True outDir
BSL.writeFile (outDir </> show revnum <.> "cabal") contents
return $ Just sm'
m' <- M.alterF go pkgId m
importIndex f es m'
_ -> importIndex f es m
importIndex _f Tar.Done m =
return m
@ -106,9 +108,9 @@ isCabalFile
Tar.entryTime = posixSecondsToUTCTime . fromIntegral -> time
}
| ".cabal" `isSuffixOf` path =
let [pkgName, pkgVersion, _] = splitDirectories path
Just name = simpleParsec pkgName
Just version = simpleParsec pkgVersion
packageId = PackageIdentifier name version
in Just (packageId, contents, time)
let [pkgName, pkgVersion, _] = splitDirectories path
Just name = simpleParsec pkgName
Just version = simpleParsec pkgVersion
packageId = PackageIdentifier name version
in Just (packageId, contents, time)
isCabalFile _ = Nothing

View File

@ -13,7 +13,6 @@ module Foliage.Meta
packageMetaEntryTimestamp,
readPackageMeta,
writePackageMeta,
PackageVersionMeta (PackageVersionMeta, pkgId, pkgSpec),
packageVersionTimestamp,
packageVersionSource,
packageVersionRevisions,
@ -32,8 +31,6 @@ module Foliage.Meta
UTCTime,
latestRevisionNumber,
consolidateRanges,
cabalFileRevisionPath,
revisedCabalFile,
)
where
@ -50,8 +47,6 @@ import Distribution.Aeson ()
import Distribution.Parsec (simpleParsec)
import Distribution.Pretty (prettyShow)
import Distribution.Types.Orphans ()
import Distribution.Types.PackageId (PackageIdentifier (..))
import Distribution.Types.PackageName (unPackageName)
import Distribution.Types.Version (Version)
import Distribution.Types.VersionRange (VersionRange, anyVersion, intersectVersionRanges, notThisVersion)
import Distribution.Version (isAnyVersion, isNoVersion, simplifyVersionRange)
@ -59,7 +54,6 @@ import Foliage.Time (UTCTime)
import GHC.Generics (Generic)
import Network.URI (URI, parseURI)
import Network.URI.Orphans ()
import System.FilePath ((<.>), (</>))
import Toml (TomlCodec, (.=))
import Toml qualified
@ -86,14 +80,18 @@ writePackageMeta fp a = void $ Toml.encodeToFile packageMetaCodec fp a
packageMetaCodec :: TomlCodec PackageMeta
packageMetaCodec =
PackageMeta
<$> Toml.list packageMetaEntryCodec "entries" .= packageMetaEntries
<$> Toml.list packageMetaEntryCodec "entries"
.= packageMetaEntries
packageMetaEntryCodec :: TomlCodec PackageMetaEntry
packageMetaEntryCodec =
PackageMetaEntry
<$> timeCodec "timestamp" .= packageMetaEntryTimestamp
<*> Toml.arrayOf _VersionRange "preferred-versions" .= packageMetaEntryPreferred
<*> Toml.arrayOf _Version "deprecated-versions" .= packageMetaEntryDeprecated
<$> timeCodec "timestamp"
.= packageMetaEntryTimestamp
<*> Toml.arrayOf _VersionRange "preferred-versions"
.= packageMetaEntryPreferred
<*> Toml.arrayOf _Version "deprecated-versions"
.= packageMetaEntryDeprecated
_Version :: Toml.TomlBiMap Version Toml.AnyValue
_Version = Toml._TextBy showVersion parseVersion
@ -185,10 +183,14 @@ data PackageVersionSpec = PackageVersionSpec
sourceMetaCodec :: TomlCodec PackageVersionSpec
sourceMetaCodec =
PackageVersionSpec
<$> Toml.dioptional (timeCodec "timestamp") .= packageVersionTimestamp
<*> packageSourceCodec .= packageVersionSource
<*> Toml.list revisionMetaCodec "revisions" .= packageVersionRevisions
<*> withDefault False (Toml.bool "force-version") .= packageVersionForce
<$> Toml.dioptional (timeCodec "timestamp")
.= packageVersionTimestamp
<*> packageSourceCodec
.= packageVersionSource
<*> Toml.list revisionMetaCodec "revisions"
.= packageVersionRevisions
<*> withDefault False (Toml.bool "force-version")
.= packageVersionForce
readPackageVersionSpec :: FilePath -> IO PackageVersionSpec
readPackageVersionSpec = Toml.decodeFile sourceMetaCodec
@ -206,8 +208,10 @@ data RevisionSpec = RevisionSpec
revisionMetaCodec :: TomlCodec RevisionSpec
revisionMetaCodec =
RevisionSpec
<$> timeCodec "timestamp" .= revisionTimestamp
<*> Toml.int "number" .= revisionNumber
<$> timeCodec "timestamp"
.= revisionTimestamp
<*> Toml.int "number"
.= revisionNumber
timeCodec :: Toml.Key -> TomlCodec UTCTime
timeCodec key = Toml.dimap (utcToZonedTime utc) zonedTimeToUTC $ Toml.zonedTime key
@ -231,18 +235,3 @@ consolidateRanges PackageMetaEntry {packageMetaEntryPreferred, packageMetaEntryD
range =
simplifyVersionRange $
foldr intersectVersionRanges anyVersion (map notThisVersion packageMetaEntryDeprecated ++ packageMetaEntryPreferred)
data PackageVersionMeta = PackageVersionMeta
{ pkgId :: PackageIdentifier,
pkgSpec :: PackageVersionSpec
}
deriving (Show, Eq)
deriving (Generic)
cabalFileRevisionPath :: FilePath -> PackageIdentifier -> Int -> FilePath
cabalFileRevisionPath inputDir PackageIdentifier {pkgName, pkgVersion} revisionNumber =
inputDir </> unPackageName pkgName </> prettyShow pkgVersion </> "revisions" </> show revisionNumber <.> "cabal"
revisedCabalFile :: FilePath -> PackageVersionMeta -> Maybe FilePath
revisedCabalFile inputDir PackageVersionMeta {pkgId, pkgSpec} = do
cabalFileRevisionPath inputDir pkgId <$> latestRevisionNumber pkgSpec

View File

@ -1,13 +1,13 @@
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE InstanceSigs #-}
module Foliage.Meta.Aeson where
import Distribution.Types.Orphans ()
import Data.Aeson
import Data.Text
import Distribution.Types.Orphans ()
import Foliage.Meta
import Foliage.Utils.Aeson
import Network.URI (URI)
@ -20,8 +20,6 @@ deriving via MyAesonEncoding RevisionSpec instance ToJSON RevisionSpec
deriving via MyAesonEncoding PackageVersionSpec instance ToJSON PackageVersionSpec
deriving via MyAesonEncoding PackageVersionMeta instance ToJSON PackageVersionMeta
deriving via Text instance ToJSON GitHubRepo
deriving via Text instance ToJSON GitHubRev
@ -30,8 +28,8 @@ instance ToJSON PackageVersionSource where
toJSON =
genericToJSON
defaultOptions
{ sumEncoding = ObjectWithSingleField
, omitNothingFields = True
{ sumEncoding = ObjectWithSingleField,
omitNothingFields = True
}
instance ToJSON URI where

View File

@ -15,10 +15,11 @@ module Foliage.Pages
where
import Data.Aeson (KeyValue ((.=)), ToJSON, object)
import Data.Function (on)
import Data.List (groupBy, sortOn)
import Data.Function (on, (&))
import Data.List (sortOn)
import Data.List.NonEmpty qualified as NE
import Data.Maybe (fromMaybe, listToMaybe)
import Data.Ord (Down (Down))
import Data.Ord (Down (Down), comparing)
import Data.Text.Lazy.IO.Utf8 qualified as TL
import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds)
@ -26,9 +27,9 @@ import Development.Shake (Action, traced)
import Distribution.Aeson (jsonGenericPackageDescription)
import Distribution.Package (PackageIdentifier (pkgName, pkgVersion))
import Distribution.Pretty (prettyShow)
import Foliage.Meta (PackageVersionMeta (..), PackageVersionSource, PackageVersionSpec (PackageVersionSpec, packageVersionRevisions, packageVersionSource, packageVersionTimestamp), RevisionSpec (RevisionSpec, revisionTimestamp), revisedCabalFile)
import Foliage.Meta (PackageVersionSource)
import Foliage.Meta.Aeson ()
import Foliage.Shake (originalCabalFile, readGenericPackageDescription')
import Foliage.PreparePackageVersion (PreparedPackageVersion (..))
import Foliage.Utils.Aeson (MyAesonEncoding (..))
import GHC.Generics (Generic)
import System.Directory qualified as IO
@ -50,34 +51,44 @@ data AllPackagesPageEntry = AllPackagesPageEntry
allPackagesPageEntryTimestamp :: UTCTime,
allPackagesPageEntryTimestampPosix :: POSIXTime,
allPackagesPageEntrySource :: PackageVersionSource,
allPackagesPageEntryRevision :: Maybe RevisionSpec
allPackagesPageEntryLatestRevisionTimestamp :: Maybe UTCTime
}
deriving stock (Generic)
deriving (ToJSON) via MyAesonEncoding AllPackagesPageEntry
makeAllPackagesPage :: UTCTime -> FilePath -> [PackageVersionMeta] -> Action ()
makeAllPackagesPage currentTime outputDir packageVersions = do
let packages =
sortOn allPackagesPageEntryPkgId
$ map
( ( \PackageVersionMeta {pkgId, pkgSpec = PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions, packageVersionSource}} ->
AllPackagesPageEntry
{ allPackagesPageEntryPkgId = pkgId,
allPackagesPageEntryTimestamp = fromMaybe currentTime packageVersionTimestamp,
allPackagesPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime packageVersionTimestamp),
allPackagesPageEntrySource = packageVersionSource,
allPackagesPageEntryRevision = listToMaybe packageVersionRevisions
}
)
. head
. sortOn (Down . pkgVersion . pkgId)
)
$ groupBy ((==) `on` (pkgName . pkgId)) packageVersions
makeAllPackagesPage :: UTCTime -> FilePath -> [PreparedPackageVersion] -> Action ()
makeAllPackagesPage currentTime outputDir packageVersions =
traced "webpages / all-packages" $ do
IO.createDirectoryIfMissing True (outputDir </> "all-packages")
TL.writeFile (outputDir </> "all-packages" </> "index.html") $
renderMustache allPackagesPageTemplate $
object ["packages" .= packages]
where
packages =
packageVersions
-- group package versions by package name
& NE.groupBy ((==) `on` (pkgName . pkgId))
-- for each package name pick the most recent version
& map
( \group ->
group
-- sort them from the most recent version to the least recent
& NE.sortBy (comparing $ Down . pkgVersion . pkgId)
-- pick the most recent version
& NE.head
-- turn it into the template data
& ( \(PreparedPackageVersion {pkgId, pkgTimestamp, cabalFileRevisions, pkgVersionSource}) ->
AllPackagesPageEntry
{ allPackagesPageEntryPkgId = pkgId,
allPackagesPageEntryTimestamp = fromMaybe currentTime pkgTimestamp,
allPackagesPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime pkgTimestamp),
allPackagesPageEntrySource = pkgVersionSource,
allPackagesPageEntryLatestRevisionTimestamp = fst <$> listToMaybe cabalFileRevisions
}
)
)
-- sort packages by pkgId
& sortOn allPackagesPageEntryPkgId
data AllPackageVersionsPageEntry
= AllPackageVersionsPageEntryPackage
@ -94,47 +105,49 @@ data AllPackageVersionsPageEntry
deriving stock (Generic)
deriving (ToJSON) via MyAesonEncoding AllPackageVersionsPageEntry
makeAllPackageVersionsPage :: UTCTime -> FilePath -> [PackageVersionMeta] -> Action ()
makeAllPackageVersionsPage currentTime outputDir packageVersions = do
let entries =
sortOn (Down . allPackageVersionsPageEntryTimestamp) $
foldMap
( \PackageVersionMeta {pkgId, pkgSpec = PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions, packageVersionSource}} ->
AllPackageVersionsPageEntryPackage
{ allPackageVersionsPageEntryPkgId = pkgId,
allPackageVersionsPageEntryTimestamp = fromMaybe currentTime packageVersionTimestamp,
allPackageVersionsPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime packageVersionTimestamp),
allPackageVersionsPageEntrySource = packageVersionSource
}
: map
( \RevisionSpec {revisionTimestamp} ->
AllPackageVersionsPageEntryRevision
{ allPackageVersionsPageEntryPkgId = pkgId,
allPackageVersionsPageEntryTimestamp = revisionTimestamp,
allPackageVersionsPageEntryTimestampPosix = utcTimeToPOSIXSeconds revisionTimestamp
}
)
packageVersionRevisions
)
packageVersions
makeAllPackageVersionsPage :: UTCTime -> FilePath -> [PreparedPackageVersion] -> Action ()
makeAllPackageVersionsPage currentTime outputDir packageVersions =
traced "webpages / all-package-versions" $ do
IO.createDirectoryIfMissing True (outputDir </> "all-package-versions")
TL.writeFile (outputDir </> "all-package-versions" </> "index.html") $
renderMustache allPackageVersionsPageTemplate $
object ["entries" .= entries]
where
entries =
-- collect all cabal file revisions including the original cabal file
foldMap
( \PreparedPackageVersion {pkgId, pkgTimestamp, pkgVersionSource, cabalFileRevisions} ->
-- original cabal file
AllPackageVersionsPageEntryPackage
{ allPackageVersionsPageEntryPkgId = pkgId,
allPackageVersionsPageEntryTimestamp = fromMaybe currentTime pkgTimestamp,
allPackageVersionsPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime pkgTimestamp),
allPackageVersionsPageEntrySource = pkgVersionSource
}
-- list of revisions
: [ AllPackageVersionsPageEntryRevision
{ allPackageVersionsPageEntryPkgId = pkgId,
allPackageVersionsPageEntryTimestamp = revisionTimestamp,
allPackageVersionsPageEntryTimestampPosix = utcTimeToPOSIXSeconds revisionTimestamp
}
| (revisionTimestamp, _) <- cabalFileRevisions
]
)
packageVersions
-- sort them by timestamp
& sortOn (Down . allPackageVersionsPageEntryTimestamp)
makePackageVersionPage :: FilePath -> FilePath -> PackageVersionMeta -> Action ()
makePackageVersionPage inputDir outputDir pkgMeta@PackageVersionMeta {pkgId, pkgSpec} = do
cabalFilePath <- maybe (originalCabalFile pkgMeta) pure (revisedCabalFile inputDir pkgMeta)
pkgDesc <- readGenericPackageDescription' cabalFilePath
makePackageVersionPage :: FilePath -> PreparedPackageVersion -> Action ()
makePackageVersionPage outputDir PreparedPackageVersion {pkgId, pkgTimestamp, pkgVersionSource, pkgDesc, cabalFileRevisions} = do
traced ("webpages / package / " ++ prettyShow pkgId) $ do
IO.createDirectoryIfMissing True (outputDir </> "package" </> prettyShow pkgId)
TL.writeFile (outputDir </> "package" </> prettyShow pkgId </> "index.html") $
renderMustache packageVersionPageTemplate $
object
[ "pkgSpec" .= pkgSpec,
"pkgDesc" .= jsonGenericPackageDescription pkgDesc
[ "pkgVersionSource" .= pkgVersionSource,
"cabalFileRevisions" .= map fst cabalFileRevisions,
"pkgDesc" .= jsonGenericPackageDescription pkgDesc,
"pkgTimestamp" .= pkgTimestamp
]
indexPageTemplate :: Template

View File

@ -0,0 +1,132 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
module Foliage.PreparePackageVersion
( PreparedPackageVersion
( pkgId,
pkgTimestamp,
pkgVersionSource,
pkgVersionForce,
pkgDesc,
sdistPath,
cabalFilePath,
originalCabalFilePath,
cabalFileRevisions
),
pattern PreparedPackageVersion,
preparePackageVersion,
)
where
import Control.Monad (unless)
import Data.List (sortOn)
import Data.Ord (Down (Down))
import Development.Shake (Action)
import Development.Shake.FilePath (joinPath, splitDirectories)
import Distribution.Client.Compat.Prelude (fromMaybe, prettyShow)
import Distribution.Parsec (simpleParsec)
import Distribution.Types.GenericPackageDescription (GenericPackageDescription (packageDescription))
import Distribution.Types.PackageDescription (PackageDescription (package))
import Distribution.Types.PackageId
import Foliage.Meta (PackageVersionSource, PackageVersionSpec (..), RevisionSpec (..), UTCTime, latestRevisionNumber)
import Foliage.PrepareSdist (prepareSdist)
import Foliage.PrepareSource (prepareSource)
import Foliage.Shake (readGenericPackageDescription', readPackageVersionSpec')
import System.FilePath (takeBaseName, takeFileName, (<.>), (</>))
data PreparedPackageVersion = PreparedPackageVersion
{ pkgId :: PackageId,
pkgTimestamp :: Maybe UTCTime,
pkgVersionSource :: PackageVersionSource,
pkgVersionForce :: Bool,
pkgDesc :: GenericPackageDescription,
sdistPath :: FilePath,
cabalFilePath :: FilePath,
originalCabalFilePath :: FilePath,
cabalFileRevisions :: [(UTCTime, FilePath)]
}
preparePackageVersion :: FilePath -> FilePath -> Action PreparedPackageVersion
preparePackageVersion inputDir metaFile = do
let (name, version) = case splitDirectories metaFile of
[n, v, _] -> (n, v)
_else -> error $ "internal error: I should not be looking at " ++ metaFile
let pkgName = fromMaybe (error $ "invalid package name: " ++ name) $ simpleParsec name
let pkgVersion = fromMaybe (error $ "invalid package version: " ++ version) $ simpleParsec version
let pkgId = PackageIdentifier pkgName pkgVersion
pkgSpec <-
readPackageVersionSpec' (inputDir </> metaFile) >>= \case
PackageVersionSpec {packageVersionRevisions, packageVersionTimestamp = Nothing}
| not (null packageVersionRevisions) -> do
error $
unlines
[ inputDir </> metaFile <> " has cabal file revisions but the original package has no timestamp.",
"This combination doesn't make sense. Either add a timestamp on the original package or remove the revisions"
]
PackageVersionSpec {packageVersionRevisions, packageVersionTimestamp = Just pkgTs}
| any ((< pkgTs) . revisionTimestamp) packageVersionRevisions -> do
error $
unlines
[ inputDir </> metaFile <> " has a revision with timestamp earlier than the package itself.",
"Adjust the timestamps so that all revisions come after the original package"
]
meta ->
return meta
srcDir <- prepareSource pkgId pkgSpec
let originalCabalFilePath = srcDir </> prettyShow pkgName <.> "cabal"
cabalFileRevisionPath revisionNumber =
joinPath
[ inputDir,
prettyShow pkgName,
prettyShow pkgVersion,
"revisions",
show revisionNumber
]
<.> "cabal"
let cabalFilePath =
maybe
originalCabalFilePath
cabalFileRevisionPath
(latestRevisionNumber pkgSpec)
pkgDesc <- readGenericPackageDescription' cabalFilePath
sdistPath <- prepareSdist srcDir
let expectedSdistName = prettyShow pkgId <.> "tar.gz"
unless (takeFileName sdistPath == expectedSdistName) $ do
error $
unlines
[ "creating a source distribution for " ++ prettyShow pkgId ++ " has failed because",
"cabal has produced a source distribtion that does not match the expected file name:",
"actual: " ++ takeBaseName sdistPath,
"expected: " ++ expectedSdistName,
"possible cause: the package name and/or version implied by the metadata file path does not match what is contained in the cabal file",
"metadata file: " ++ metaFile,
"version in cabal file: " ++ prettyShow (Distribution.Types.PackageId.pkgVersion $ package $ packageDescription pkgDesc)
]
let cabalFileRevisions =
sortOn
(Down . fst)
[ (revisionTimestamp, cabalFileRevisionPath revisionNumber)
| RevisionSpec {revisionTimestamp, revisionNumber} <- packageVersionRevisions pkgSpec
]
return
PreparedPackageVersion
{ pkgId,
pkgTimestamp = packageVersionTimestamp pkgSpec,
pkgVersionSource = packageVersionSource pkgSpec,
pkgVersionForce = packageVersionForce pkgSpec,
pkgDesc,
sdistPath,
cabalFilePath,
originalCabalFilePath,
cabalFileRevisions
}

View File

@ -1,7 +1,6 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
module Foliage.PrepareSdist
@ -53,7 +52,7 @@ addPrepareSdistRule outputDirRoot = addBuiltinRule noLint noIdentity run
case ehvExisting of
Right hvExisting
| hvExisting == hvExpected ->
return RunResult {runChanged = ChangedNothing, runStore = old, runValue = path}
return RunResult {runChanged = ChangedNothing, runStore = old, runValue = path}
Right hvExisting -> do
putWarn $ "Changed " ++ path ++ " (expecting hash " ++ showHashValue hvExpected ++ " found " ++ showHashValue hvExisting ++ "). I will rebuild it."
run (PrepareSdistRule srcDir) (Just old) RunDependenciesChanged
@ -71,18 +70,24 @@ addPrepareSdistRule outputDirRoot = addBuiltinRule noLint noIdentity run
_differentOrMissing -> ChangedRecomputeDiff
when (changed == ChangedRecomputeSame) $
putInfo $ "Wrote " ++ path ++ " (same hash " ++ showHashValue hv ++ ")"
putInfo ("Wrote " ++ path ++ " (same hash " ++ showHashValue hv ++ ")")
when (changed == ChangedRecomputeDiff) $
putInfo $ "Wrote " ++ path ++ " (new hash " ++ showHashValue hv ++ ")"
putInfo ("Wrote " ++ path ++ " (new hash " ++ showHashValue hv ++ ")")
return $ RunResult {runChanged = changed, runStore = new, runValue = path}
makeSdist srcDir = do
cabalFile <- do
getDirectoryFiles srcDir ["*.cabal"] >>= \case
[f] -> pure f
fs -> fail $ "Invalid srcDir: " ++ srcDir ++ ". It contains multiple cabal files: " ++ unwords fs
cabalFiles <- getDirectoryFiles srcDir ["*.cabal"]
let cabalFile = case cabalFiles of
[f] -> f
fs ->
error $
unlines
[ "Invalid source directory: " ++ srcDir,
"It contains multiple cabal files, while only one is allowed",
unwords fs
]
traced "cabal sdist" $ do
gpd <- readGenericPackageDescription Verbosity.normal (srcDir </> cabalFile)

View File

@ -35,14 +35,16 @@ addFetchRemoteAssetRule cacheDir = addBuiltinRule noLint noIdentity run
run :: BuiltinRun RemoteAsset FilePath
run (RemoteAsset uri) old _mode = do
unless (uriQuery uri == "") $
fail $ "Query elements in URI are not supported: " <> show uri
error ("Query elements in URI are not supported: " <> show uri)
unless (uriFragment uri == "") $
fail $ "Fragments in URI are not supported: " <> show uri
error ("Fragments in URI are not supported: " <> show uri)
let scheme = dropWhileEnd (not . isAlpha) $ uriScheme uri
Just host = uriRegName <$> uriAuthority uri
path = cacheDir </> joinPath (scheme : host : pathSegments uri)
let host = maybe (error $ "invalid uri " ++ show uri) uriRegName (uriAuthority uri)
let path = cacheDir </> joinPath (scheme : host : pathSegments uri)
-- parse etag from store
let oldETag = fromMaybe BS.empty old

View File

@ -3,7 +3,6 @@ module Foliage.Shake
readKeysAt,
readPackageVersionSpec',
readGenericPackageDescription',
originalCabalFile,
)
where
@ -12,12 +11,9 @@ import Development.Shake
import Development.Shake.FilePath
import Distribution.Simple.PackageDescription
import Distribution.Types.GenericPackageDescription
import Distribution.Types.PackageId
import Distribution.Types.PackageName
import Distribution.Verbosity qualified as Verbosity
import Foliage.HackageSecurity
import Foliage.Meta
import Foliage.PrepareSource
computeFileInfoSimple' :: FilePath -> Action FileInfo
computeFileInfoSimple' fp = do
@ -41,8 +37,3 @@ readGenericPackageDescription' :: FilePath -> Action GenericPackageDescription
readGenericPackageDescription' fp = do
need [fp]
liftIO $ readGenericPackageDescription Verbosity.silent fp
originalCabalFile :: PackageVersionMeta -> Action FilePath
originalCabalFile PackageVersionMeta {pkgId, pkgSpec} = do
srcDir <- prepareSource pkgId pkgSpec
return $ srcDir </> unPackageName (pkgName pkgId) <.> "cabal"

View File

@ -2,22 +2,23 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Foliage.Utils.Aeson where
import Data.Aeson
import GHC.Generics
import Data.Coerce
import GHC.Generics
newtype MyAesonEncoding a = MyAesonEncoding a
deriving Generic
deriving (Generic)
myOptions :: Options
myOptions =
defaultOptions
{ sumEncoding = ObjectWithSingleField
, omitNothingFields = True
{ sumEncoding = ObjectWithSingleField,
omitNothingFields = True
}
instance (Generic a, GToJSON' Value Zero (Rep a), GToJSON' Encoding Zero (Rep a)) => ToJSON (MyAesonEncoding a) where
toJSON = coerce (genericToJSON myOptions :: a -> Value)
toJSON = coerce (genericToJSON myOptions :: a -> Value)
toEncoding = coerce (genericToEncoding myOptions :: a -> Encoding)

View File

@ -1,3 +1,5 @@
{-# LANGUAGE LambdaCase #-}
module Main where
import Foliage.CmdBuild

View File

@ -1,6 +1,6 @@
packages: .
index-state: 2022-08-29T00:00:00Z
with-compiler: ghc-9.2.5
index-state: 2023-03-01T00:00:00Z
with-compiler: ghc-9.2.6
allow-newer:
, tomland:base
, tomland:text

View File

@ -51,11 +51,11 @@
"cabal-34": {
"flake": false,
"locked": {
"lastModified": 1640353650,
"narHash": "sha256-N1t6M3/wqj90AEdRkeC8i923gQYUpzSr8b40qVOZ1Rk=",
"lastModified": 1645834128,
"narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=",
"owner": "haskell",
"repo": "cabal",
"rev": "942639c18c0cd8ec53e0a6f8d120091af35312cd",
"rev": "5ff598c67f53f7c4f48e31d722ba37172230c462",
"type": "github"
},
"original": {
@ -68,11 +68,11 @@
"cabal-36": {
"flake": false,
"locked": {
"lastModified": 1641652457,
"narHash": "sha256-BlFPKP4C4HRUJeAbdembX1Rms1LD380q9s0qVDeoAak=",
"lastModified": 1669081697,
"narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=",
"owner": "haskell",
"repo": "cabal",
"rev": "f27667f8ec360c475027dcaee0138c937477b070",
"rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144",
"type": "github"
},
"original": {
@ -159,15 +159,16 @@
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1635892615,
"narHash": "sha256-harGbMZr4hzat2BWBU+Y5OYXlu+fVz7E4WeQzHi5o8A=",
"lastModified": 1672831974,
"narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=",
"owner": "input-output-hk",
"repo": "flake-compat",
"rev": "eca47d3377946315596da653862d341ee5341318",
"rev": "45f2638735f8cdc40fe302742b79f248d23eb368",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "hkm/gitlab-fix",
"repo": "flake-compat",
"type": "github"
}
@ -190,11 +191,11 @@
},
"flake-utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
@ -233,21 +234,6 @@
"type": "github"
}
},
"flake-utils_4": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"ghc-8.6.5-iohk": {
"flake": false,
"locked": {
@ -287,11 +273,11 @@
"hackage": {
"flake": false,
"locked": {
"lastModified": 1673137629,
"narHash": "sha256-HJfuXQ6NkhdZIMo4/S/Y9QX1xmuBS7XSB4xhmEVZSWc=",
"lastModified": 1677809131,
"narHash": "sha256-MQ+ybbu5VFA6ERvh8mXcYEVlBCTte4BDxRaILSwBdAk=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "5cc584651a4895c7abad166cf695a3ee8b873386",
"rev": "4ea4b12737ea42e47eb5c6a7e4a3eafe9da2fc52",
"type": "github"
},
"original": {
@ -329,11 +315,11 @@
"tullia": "tullia"
},
"locked": {
"lastModified": 1673139096,
"narHash": "sha256-EzMIx2nxXoHbMFHIKFiXVE6AC+PcCm4NjKChk9MAgM8=",
"lastModified": 1677809260,
"narHash": "sha256-RSiv9/LP8/+sf15B305z4DYaj7IiAVjPBkqPfByxAp4=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "f5da0a34b5dbbeb57e6d7595f46a930cd62bcd77",
"rev": "02a5acdfc937129e51e41de0eafd0c44f29896b4",
"type": "github"
},
"original": {
@ -369,11 +355,11 @@
]
},
"locked": {
"lastModified": 1646878427,
"narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=",
"lastModified": 1671755331,
"narHash": "sha256-hXsgJj0Cy0ZiCiYdW2OdBz5WmFyOMKuw4zyxKpgUKm4=",
"owner": "NixOS",
"repo": "hydra",
"rev": "28b682b85b7efc5cf7974065792a1f22203a5927",
"rev": "f48f00ee6d5727ae3e488cbf9ce157460853fea8",
"type": "github"
},
"original": {
@ -381,20 +367,44 @@
"type": "indirect"
}
},
"incl": {
"inputs": {
"nixlib": [
"haskell-nix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1669263024,
"narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=",
"owner": "divnix",
"repo": "incl",
"rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "incl",
"type": "github"
}
},
"iserv-proxy": {
"flake": false,
"locked": {
"lastModified": 1639165170,
"narHash": "sha256-QsWL/sBDL5GM8IXd/dE/ORiL4RvteEN+aok23tXgAoc=",
"rev": "6e95df7be6dd29680f983db07a057fc2f34f81f6",
"revCount": 7,
"lastModified": 1670983692,
"narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=",
"ref": "hkm/remote-iserv",
"rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300",
"revCount": 10,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/iserv-proxy.git"
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
},
"original": {
"rev": "6e95df7be6dd29680f983db07a057fc2f34f81f6",
"ref": "hkm/remote-iserv",
"type": "git",
"url": "https://gitlab.haskell.org/ghc/iserv-proxy.git"
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
}
},
"lowdown-src": {
@ -413,25 +423,14 @@
"type": "github"
}
},
"mdbook-kroki-preprocessor": {
"flake": false,
"locked": {
"lastModified": 1661755005,
"narHash": "sha256-1TJuUzfyMycWlOQH67LR63/ll2GDZz25I3JfScy/Jnw=",
"owner": "JoelCourtney",
"repo": "mdbook-kroki-preprocessor",
"rev": "93adb5716d035829efed27f65f2f0833a7d3e76f",
"type": "github"
},
"original": {
"owner": "JoelCourtney",
"repo": "mdbook-kroki-preprocessor",
"type": "github"
}
},
"n2c": {
"inputs": {
"flake-utils": "flake-utils_4",
"flake-utils": [
"haskell-nix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskell-nix",
"tullia",
@ -460,16 +459,16 @@
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1643066034,
"narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=",
"lastModified": 1661606874,
"narHash": "sha256-9+rpYzI+SmxJn+EbYxjGv68Ucp22bdFUSy/4LkHkkDQ=",
"owner": "NixOS",
"repo": "nix",
"rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62",
"rev": "11e45768b34fdafdcf019ddbd337afa16127ff0f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "2.6.0",
"ref": "2.11.0",
"repo": "nix",
"type": "github"
}
@ -565,17 +564,18 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1632864508,
"narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=",
"lastModified": 1657693803,
"narHash": "sha256-G++2CJ9u0E7NNTAi9n5G8TdDmGJXcIjkJ3NF8cetQB8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "82891b5e2c2359d7e58d08849e4c89511ab94234",
"rev": "365e1b3a859281cf11b94f87231adeabbdd878a2",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-21.05-small",
"type": "indirect"
"owner": "NixOS",
"ref": "nixos-22.05-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2003": {
@ -628,11 +628,11 @@
},
"nixpkgs-2205": {
"locked": {
"lastModified": 1663981975,
"narHash": "sha256-TKaxWAVJR+a5JJauKZqibmaM5e/Pi5tBDx9s8fl/kSE=",
"lastModified": 1672580127,
"narHash": "sha256-3lW3xZslREhJogoOkjeZtlBtvFMyxHku7I/9IVehhT8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "309faedb8338d3ae8ad8f1043b3ccf48c9cc2970",
"rev": "0874168639713f547c05947c76124f78441ea46c",
"type": "github"
},
"original": {
@ -644,11 +644,11 @@
},
"nixpkgs-2211": {
"locked": {
"lastModified": 1669997163,
"narHash": "sha256-vhjC0kZMFoN6jzK0GR+tBzKi5KgBXgehadfidW8+Va4=",
"lastModified": 1675730325,
"narHash": "sha256-uNvD7fzO5hNlltNQUAFBPlcEjNG5Gkbhl/ROiX+GZU4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6f87491a54d8d64d30af6663cb3bf5d2ee7db958",
"rev": "b7ce17b1ebf600a72178f6302c77b6382d09323f",
"type": "github"
},
"original": {
@ -668,18 +668,19 @@
"type": "github"
},
"original": {
"id": "nixpkgs",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "indirect"
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1663905476,
"narHash": "sha256-0CSwRKaYravh9v6qSlBpM0gNg0UhKT2lL7Yn6Zbx7UM=",
"lastModified": 1675758091,
"narHash": "sha256-7gFSQbSVAFUHtGCNHPF7mPc5CcqDk9M2+inlVPZSneg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e14f9fb57315f0d4abde222364f19f88c77d2b79",
"rev": "747927516efcb5e31ba03b7ff32f61f6d47e7d87",
"type": "github"
},
"original": {
@ -736,6 +737,21 @@
"type": "github"
}
},
"nosys": {
"locked": {
"lastModified": 1667881534,
"narHash": "sha256-FhwJ15uPLRsvaxtt/bNuqE/ykMpNAPF0upozFKhTtXM=",
"owner": "divnix",
"repo": "nosys",
"rev": "2d0d5207f6a230e9d0f660903f8db9807b54814f",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "nosys",
"type": "github"
}
},
"old-ghc-nix": {
"flake": false,
"locked": {
@ -769,11 +785,11 @@
"stackage": {
"flake": false,
"locked": {
"lastModified": 1673050158,
"narHash": "sha256-/1WWFQDUisdEuSOUTvQTzkED9Z6riX3XuVMuaMIbyq4=",
"lastModified": 1677543037,
"narHash": "sha256-7CPQZZafTQiw7YL+a2KCamb9a3PU0do9iZKy1AaRkBo=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "46c3d80f024585ddf22a54f3c505799dca778865",
"rev": "f4d29fa4403f45541d9f3993523df6027c21fe90",
"type": "github"
},
"original": {
@ -784,17 +800,23 @@
},
"std": {
"inputs": {
"arion": [
"haskell-nix",
"tullia",
"std",
"blank"
],
"blank": "blank",
"devshell": "devshell",
"dmerge": "dmerge",
"flake-utils": "flake-utils_3",
"incl": "incl",
"makes": [
"haskell-nix",
"tullia",
"std",
"blank"
],
"mdbook-kroki-preprocessor": "mdbook-kroki-preprocessor",
"microvm": [
"haskell-nix",
"tullia",
@ -804,14 +826,15 @@
"n2c": "n2c",
"nixago": "nixago",
"nixpkgs": "nixpkgs_4",
"nosys": "nosys",
"yants": "yants"
},
"locked": {
"lastModified": 1665513321,
"narHash": "sha256-D6Pacw9yf/HMs84KYuCxHXnNDL7v43gtcka5URagFqE=",
"lastModified": 1674526466,
"narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=",
"owner": "divnix",
"repo": "std",
"rev": "94a90eedb9cfc115b12ae8f6622d9904788559e4",
"rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826",
"type": "github"
},
"original": {
@ -831,11 +854,11 @@
"std": "std"
},
"locked": {
"lastModified": 1668711738,
"narHash": "sha256-CBjky16o9pqsGE1bWu6nRlRajgSXMEk+yaFQLibqXcE=",
"lastModified": 1675695930,
"narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=",
"owner": "input-output-hk",
"repo": "tullia",
"rev": "ead1f515c251f0e060060ef0e2356a51d3dfe4b0",
"rev": "621365f2c725608f381b3ad5b57afef389fd4c31",
"type": "github"
},
"original": {
@ -869,11 +892,11 @@
]
},
"locked": {
"lastModified": 1660507851,
"narHash": "sha256-BKjq7JnVuUR/xDtcv6Vm9GYGKAblisXrAgybor9hT/s=",
"lastModified": 1667096281,
"narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=",
"owner": "divnix",
"repo": "yants",
"rev": "0b895ca02a8fa72bad50b454cb3e7d8a66407c96",
"rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c",
"type": "github"
},
"original": {

View File

@ -10,7 +10,7 @@
outputs = { self, nixpkgs, flake-utils, haskell-nix }:
flake-utils.lib.eachDefaultSystem (system:
flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
let
pkgs = import nixpkgs {
inherit system;
@ -18,27 +18,24 @@
overlays = [ haskell-nix.overlay ];
};
pkgs-static-where-possible = if pkgs.stdenv.hostPlatform.isLinux then
if pkgs.stdenv.hostPlatform.isAarch64 then
pkgs.pkgsCross.aarch64-multiplatform-musl
pkgs-static-where-possible =
if pkgs.stdenv.hostPlatform.isLinux then
if pkgs.stdenv.hostPlatform.isAarch64 then
pkgs.pkgsCross.aarch64-multiplatform-musl
else
pkgs.pkgsCross.musl64
else
pkgs.pkgsCross.musl64
else
pkgs;
pkgs;
project = pkgs-static-where-possible.haskell-nix.cabalProject' {
src = ./.;
compiler-nix-name = "ghc8107";
shell.tools = {
cabal = { };
hlint = { };
haskell-language-server = { };
};
compiler-nix-name = "ghc926";
};
flake = project.flake { };
in flake // { packages.default = flake.packages."foliage:exe:foliage"; });
in
flake // { packages.default = flake.packages."foliage:exe:foliage"; });
nixConfig = {
extra-substituters = [

View File

@ -27,6 +27,7 @@ executable foliage
Foliage.Meta.Aeson
Foliage.Options
Foliage.Pages
Foliage.PreparePackageVersion
Foliage.PrepareSource
Foliage.PrepareSdist
Foliage.RemoteAsset
@ -37,9 +38,7 @@ executable foliage
Foliage.Utils.GitHub
Network.URI.Orphans
default-language: Haskell2010
default-extensions:
ImportQualifiedPost LambdaCase NamedFieldPuns ViewPatterns
default-language: GHC2021
ghc-options: -Wall
ghc-options: -threaded

View File

@ -42,28 +42,26 @@
<dt class="col-sm-3">License</dt>
<dd class="col-sm-9"><p>{{license}}</p></dd>
{{/pkgDesc}}
{{#pkgSpec}}
{{#packageVersionSource}}
{{#pkgVersionSource}}
<dt class="col-sm-3">Source</dt>
<dd class="col-sm-9">
<dl class="row">
{{> packageVersionSource}}
</dl>
</dd>
{{/packageVersionSource}}
{{/pkgVersionSource}}
<dt class="col-sm-3">Timestamp</dt>
<dd class="col-sm-9"><p>{{packageVersionTimestamp}}</p></dd>
<dd class="col-sm-9"><p>{{pkgTimestamp}}</p></dd>
<dt class="col-sm-3">Revisions</dt>
<dd class="col-sm-9">
{{#packageVersionRevisions}}
<p>{{revisionTimestamp}}</p>
{{/packageVersionRevisions}}
{{^packageVersionRevisions}}
{{#cabalFileRevisions}}
<p>{{.}}</p>
{{/cabalFileRevisions}}
{{^cabalFileRevisions}}
<p>None</p>
{{/packageVersionRevisions}}
{{/cabalFileRevisions}}
</dd>
</dl>
</div>
{{/pkgSpec}}
</body>
</html>