mirror of
https://github.com/input-output-hk/foliage.git
synced 2024-09-11 20:27:09 +03:00
Merge pull request #37 from andreabedini/add-consistency-check
Add consistency check
This commit is contained in:
commit
20049b1e81
@ -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 ()
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
132
app/Foliage/PreparePackageVersion.hs
Normal file
132
app/Foliage/PreparePackageVersion.hs
Normal 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
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -1,3 +1,5 @@
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
|
||||
module Main where
|
||||
|
||||
import Foliage.CmdBuild
|
||||
|
@ -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
|
||||
|
211
flake.lock
211
flake.lock
@ -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": {
|
||||
|
25
flake.nix
25
flake.nix
@ -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 = [
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user