Merge branch 'main' into dont-autogenerate-keys

This commit is contained in:
Ben Gamari 2023-03-21 15:32:52 -04:00 committed by GitHub
commit add45abbb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1031 additions and 344 deletions

View File

@ -12,18 +12,16 @@ jobs:
- ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: cachix/install-nix-action@v17
- uses: cachix/install-nix-action@v20
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
substituters = https://cache.iog.io https://cache.nixos.org
- uses: cachix/cachix-action@v10
- uses: cachix/cachix-action@v12
with:
name: foliage
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix build
- run: nix build --accept-flake-config

27
.github/workflows/update-flake-lock.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Nix
uses: cachix/install-nix-action@v19
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@v16
with:
pr-title: "Update flake.lock" # Title of PR to be created
pr-labels: | # Labels to be set on the PR
dependencies
automated
- name: Print PR number
run: echo Opened pull request ${{ steps.update.outputs.pull-request-number }}.

View File

@ -273,6 +273,18 @@ metadata file `<package>/<version>/meta.toml` includes the option
`force-version = true`, then the version in the package cabal file will be
overwritten with `<version>`. Notice this is done after applying patches.
# Accessing private repositories
Foliage uses curl to fetch remote assets. If you need to access private
repositories you can use one of the following methods.
- You can instruct curl to use a netrc file.
- Add netrc-optional to ~/.curlrc (see [here](https://curl.se/docs/manpage.html#-K) for the places curl looks in).
- Add the relevant credentials to ~/.netrc
- You can also add the credentials directly to curl's configuration, e.g.
- Add `user = "USERNAME:PASSWORD"` to .curlrc in the current directly
- Set `CURL_HOME=$PWD`
## Author
- Andrea Bedini (@andreabedini)

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

@ -6,29 +6,32 @@ module Foliage.CmdBuild (cmdBuild) where
import Codec.Archive.Tar qualified as Tar
import Codec.Archive.Tar.Entry qualified as Tar
import Codec.Compression.GZip qualified as GZip
import Control.Monad (unless, when)
import Control.Monad (unless, void, when)
import Data.Aeson qualified as Aeson
import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as BL
import Data.ByteString.Lazy qualified as BSL
import Data.Foldable (for_)
import Data.List (sortOn)
import Data.Maybe (fromMaybe)
import Data.Text qualified as T
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
import Hackage.Security.Util.Path (castRoot, toFilePath)
import Network.URI (URI (uriPath, uriQuery, uriScheme), nullURI)
import System.Directory (createDirectoryIfMissing)
cmdBuild :: BuildOptions -> IO ()
cmdBuild buildOptions = do
@ -45,7 +48,8 @@ cmdBuild buildOptions = do
opts =
shakeOptions
{ shakeFiles = cacheDir,
shakeVerbosity = Verbose
shakeVerbosity = Verbose,
shakeThreads = buildOptsNumThreads buildOptions
}
buildAction :: BuildOptions -> Action ()
@ -55,7 +59,8 @@ buildAction
buildOptsCurrentTime = mCurrentTime,
buildOptsExpireSignaturesOn = mExpireSignaturesOn,
buildOptsInputDir = inputDir,
buildOptsOutputDir = outputDir
buildOptsOutputDir = outputDir,
buildOptsWriteMetadata = doWritePackageMeta
} = do
outputDirRoot <- liftIO $ makeAbsolute (fromFilePath outputDir)
@ -94,54 +99,47 @@ buildAction
makeAllPackageVersionsPage currentTime outputDir packageVersions
for_ packageVersions $ makePackageVersionPage inputDir outputDir
when doWritePackageMeta $
makeMetadataFile outputDir packageVersions
for_ packageVersions $ \pkgMeta@PackageVersionMeta {pkgId} -> do
void $ forP packageVersions $ makePackageVersionPage outputDir
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
)
packageVersions
targetKeys <- maybeReadKeysAt "target"
metadataEntries <-
for 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
BSL.writeFile (anchorPath outputDirRoot repoLayoutIndexTar) tarContents
BSL.writeFile (anchorPath outputDirRoot repoLayoutIndexTarGz) $ GZip.compress tarContents
BL.writeFile (anchorPath outputDirRoot repoLayoutIndexTar) tarContents
BL.writeFile (anchorPath outputDirRoot repoLayoutIndexTarGz) $ GZip.compress tarContents
privateKeysRoot <- maybeReadKeysAt "root"
privateKeysTarget <- maybeReadKeysAt "target"
@ -226,58 +224,66 @@ buildAction
timestampInfoSnapshot = snapshotInfo
}
getPackageVersions :: FilePath -> Action [PackageVersionMeta]
makeMetadataFile :: FilePath -> [PreparedPackageVersion] -> Action ()
makeMetadataFile outputDir packageVersions = traced "writing metadata" $ do
createDirectoryIfMissing True (outputDir </> "foliage")
Aeson.encodeFile
(outputDir </> "foliage" </> "packages.json")
(map encodePackageVersion packageVersions)
where
encodePackageVersion
PreparedPackageVersion
{ pkgId = PackageIdentifier {pkgName, pkgVersion},
pkgTimestamp,
pkgVersionForce,
pkgVersionSource
} =
Aeson.object
( [ "pkg-name" Aeson..= pkgName,
"pkg-version" Aeson..= pkgVersion,
"url" Aeson..= sourceUrl pkgVersionSource
]
++ ["forced-version" Aeson..= True | pkgVersionForce]
++ (case pkgTimestamp of Nothing -> []; Just t -> ["timestamp" Aeson..= t])
)
sourceUrl :: PackageVersionSource -> URI
sourceUrl (TarballSource uri Nothing) = uri
sourceUrl (TarballSource uri (Just subdir)) = uri {uriQuery = "?dir=" ++ subdir}
sourceUrl (GitHubSource repo rev Nothing) =
nullURI
{ uriScheme = "github:",
uriPath = T.unpack (unGitHubRepo repo) </> T.unpack (unGitHubRev rev)
}
sourceUrl (GitHubSource repo rev (Just subdir)) =
nullURI
{ uriScheme = "github:",
uriPath = T.unpack (unGitHubRepo repo) </> T.unpack (unGitHubRev rev),
uriQuery = "?dir=" ++ subdir
}
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"
for 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 $ BSL.readFile filePath
return $ mkTarEntry contents (IndexPkgCabal pkgId) timestamp
contents <- liftIO $ BS.readFile filePath
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 <- liftIO $ computeFileInfoSimple sdistPath
let packagePath = repoLayoutPkgTarGz hackageRepoLayout pkgId
return
Targets
@ -287,7 +293,7 @@ prepareIndexPkgMetadata expiryTime PackageVersionMeta {pkgId, pkgSpec} = do
targetsDelegations = Nothing
}
mkTarEntry :: BSL.ByteString -> IndexFile dec -> UTCTime -> Tar.Entry
mkTarEntry :: BL.ByteString -> IndexFile dec -> UTCTime -> Tar.Entry
mkTarEntry contents indexFile timestamp =
(Tar.fileEntry tarPath contents)
{ Tar.entryTime = floor $ Time.utcTimeToPOSIXSeconds timestamp,
@ -300,8 +306,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

@ -51,7 +51,9 @@ data BuildOptions = BuildOptions
buildOptsCurrentTime :: Maybe UTCTime,
buildOptsExpireSignaturesOn :: Maybe UTCTime,
buildOptsInputDir :: FilePath,
buildOptsOutputDir :: FilePath
buildOptsOutputDir :: FilePath,
buildOptsNumThreads :: Int,
buildOptsWriteMetadata :: Bool
}
buildCommand :: Parser Command
@ -90,6 +92,20 @@ buildCommand =
<> showDefault
<> value "_repo"
)
<*> option
auto
( long "num-jobs"
<> short 'j'
<> metavar "JOBS"
<> help "Number of jobs to run in parallel, 0 is 'all available cores'"
<> showDefault
<> value 1
)
<*> switch
( long "write-metadata"
<> help "Write metadata in the output-directory"
<> showDefault
)
)
where
signOpts =

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

@ -8,7 +8,6 @@ module Foliage.PrepareSource where
import Control.Monad (when)
import Data.ByteString qualified as BS
import Data.Foldable (for_)
import Data.Text qualified as T
import Development.Shake
import Development.Shake.Classes
import Development.Shake.Rule
@ -18,8 +17,8 @@ import Distribution.Types.PackageName (unPackageName)
import Foliage.Meta
import Foliage.RemoteAsset (fetchRemoteAsset)
import Foliage.UpdateCabalFile (rewritePackageVersion)
import Foliage.Utils.GitHub (githubRepoTarballUrl)
import GHC.Generics
import Network.URI (URI (..), URIAuth (..), nullURI, nullURIAuth)
import System.Directory qualified as IO
import System.FilePath ((<.>), (</>))
@ -79,12 +78,7 @@ addPrepareSourceRule inputDir cacheDir = addBuiltinRule noLint noIdentity run
-- metadata.
--
GitHubSource repo rev mSubdir -> do
let url =
nullURI
{ uriScheme = "https:",
uriAuthority = Just nullURIAuth {uriRegName = "github.com"},
uriPath = "/" </> T.unpack (unGitHubRepo repo) </> "tarball" </> T.unpack (unGitHubRev rev)
}
let url = githubRepoTarballUrl repo rev
tarballPath <- fetchRemoteAsset url

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

@ -0,0 +1,17 @@
module Foliage.Utils.GitHub
( githubRepoTarballUrl,
)
where
import Data.Text qualified as T
import Foliage.Meta (GitHubRepo (unGitHubRepo), GitHubRev (unGitHubRev))
import Network.URI (URI (..), URIAuth (..), nullURI, nullURIAuth)
import System.FilePath ((</>))
githubRepoTarballUrl :: GitHubRepo -> GitHubRev -> URI
githubRepoTarballUrl repo rev =
nullURI
{ uriScheme = "https:",
uriAuthority = Just nullURIAuth {uriRegName = "github.com"},
uriPath = "/" </> T.unpack (unGitHubRepo repo) </> "tarball" </> T.unpack (unGitHubRev rev)
}

View File

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

View File

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

View File

@ -16,6 +16,21 @@
"type": "github"
}
},
"blank": {
"locked": {
"lastModified": 1625557891,
"narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=",
"owner": "divnix",
"repo": "blank",
"rev": "5a5d2684073d9f563072ed07c871d577a6c614a8",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "blank",
"type": "github"
}
},
"cabal-32": {
"flake": false,
"locked": {
@ -36,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": {
@ -53,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": {
@ -83,13 +98,104 @@
"type": "github"
}
},
"devshell": {
"inputs": {
"flake-utils": [
"haskell-nix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskell-nix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1663445644,
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
"owner": "numtide",
"repo": "devshell",
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"dmerge": {
"inputs": {
"nixlib": [
"haskell-nix",
"tullia",
"std",
"nixpkgs"
],
"yants": [
"haskell-nix",
"tullia",
"std",
"yants"
]
},
"locked": {
"lastModified": 1659548052,
"narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=",
"owner": "divnix",
"repo": "data-merge",
"rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "data-merge",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1672831974,
"narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=",
"owner": "input-output-hk",
"repo": "flake-compat",
"rev": "45f2638735f8cdc40fe302742b79f248d23eb368",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "hkm/gitlab-fix",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
@ -100,11 +206,26 @@
},
"flake-utils_2": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
@ -130,14 +251,33 @@
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"nixpkgs": "nixpkgs_2",
"utils": "utils"
},
"locked": {
"lastModified": 1655245309,
"narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=",
"owner": "tweag",
"repo": "gomod2nix",
"rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58",
"type": "github"
},
"original": {
"owner": "tweag",
"repo": "gomod2nix",
"type": "github"
}
},
"hackage": {
"flake": false,
"locked": {
"lastModified": 1661735830,
"narHash": "sha256-xJpfFmpzJVci+fM9mjTKyIbkUpJf5XkZMygY+YRKzwU=",
"lastModified": 1677809131,
"narHash": "sha256-MQ+ybbu5VFA6ERvh8mXcYEVlBCTte4BDxRaILSwBdAk=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "9b22f61f50b19bf401ab104ff0e239f8ada87547",
"rev": "4ea4b12737ea42e47eb5c6a7e4a3eafe9da2fc52",
"type": "github"
},
"original": {
@ -153,12 +293,13 @@
"cabal-34": "cabal-34",
"cabal-36": "cabal-36",
"cardano-shell": "cardano-shell",
"flake-utils": "flake-utils_2",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"ghc-8.6.5-iohk": "ghc-8.6.5-iohk",
"hackage": "hackage",
"hpc-coveralls": "hpc-coveralls",
"hydra": "hydra",
"nix-tools": "nix-tools",
"iserv-proxy": "iserv-proxy",
"nixpkgs": [
"haskell-nix",
"nixpkgs-unstable"
@ -167,16 +308,18 @@
"nixpkgs-2105": "nixpkgs-2105",
"nixpkgs-2111": "nixpkgs-2111",
"nixpkgs-2205": "nixpkgs-2205",
"nixpkgs-2211": "nixpkgs-2211",
"nixpkgs-unstable": "nixpkgs-unstable",
"old-ghc-nix": "old-ghc-nix",
"stackage": "stackage"
"stackage": "stackage",
"tullia": "tullia"
},
"locked": {
"lastModified": 1661940924,
"narHash": "sha256-aXmYSdeDjSWpJPtNAtvAKabKUyOOiJXzZ7EEYYKNrYI=",
"lastModified": 1677809260,
"narHash": "sha256-RSiv9/LP8/+sf15B305z4DYaj7IiAVjPBkqPfByxAp4=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "c83b33f4198fd8ba62748feb5024ece2b5329a8e",
"rev": "02a5acdfc937129e51e41de0eafd0c44f29896b4",
"type": "github"
},
"original": {
@ -212,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": {
@ -224,6 +367,46 @@
"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": 1670983692,
"narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=",
"ref": "hkm/remote-iserv",
"rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300",
"revCount": 10,
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
},
"original": {
"ref": "hkm/remote-iserv",
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
}
},
"lowdown-src": {
"flake": false,
"locked": {
@ -240,6 +423,35 @@
"type": "github"
}
},
"n2c": {
"inputs": {
"flake-utils": [
"haskell-nix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskell-nix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1665039323,
"narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
@ -247,49 +459,123 @@
"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"
}
},
"nix-tools": {
"flake": false,
"nix-nomad": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-utils": [
"haskell-nix",
"tullia",
"nix2container",
"flake-utils"
],
"gomod2nix": "gomod2nix",
"nixpkgs": [
"haskell-nix",
"tullia",
"nixpkgs"
],
"nixpkgs-lib": [
"haskell-nix",
"tullia",
"nixpkgs"
]
},
"locked": {
"lastModified": 1659569011,
"narHash": "sha256-wHS0H5+TERmDnPCfzH4A+rSR5TvjYMWus9BNeNAMyUM=",
"owner": "input-output-hk",
"repo": "nix-tools",
"rev": "555d57e1ea81b79945f2608aa261df20f6b602a5",
"lastModified": 1658277770,
"narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=",
"owner": "tristanpemble",
"repo": "nix-nomad",
"rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "nix-tools",
"owner": "tristanpemble",
"repo": "nix-nomad",
"type": "github"
}
},
"nix2container": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1658567952,
"narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "60bb43d405991c1378baf15a40b5811a53e32ffa",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"type": "github"
}
},
"nixago": {
"inputs": {
"flake-utils": [
"haskell-nix",
"tullia",
"std",
"flake-utils"
],
"nixago-exts": [
"haskell-nix",
"tullia",
"std",
"blank"
],
"nixpkgs": [
"haskell-nix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1661824785,
"narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=",
"owner": "nix-community",
"repo": "nixago",
"rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixago",
"type": "github"
}
},
"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": {
@ -310,11 +596,11 @@
},
"nixpkgs-2105": {
"locked": {
"lastModified": 1655034179,
"narHash": "sha256-rf1/7AbzuYDw6+8Xvvf3PtEOygymLBrFsFxvext5ZjI=",
"lastModified": 1659914493,
"narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "046ee4af7a9f016a364f8f78eeaa356ba524ac31",
"rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf",
"type": "github"
},
"original": {
@ -326,11 +612,11 @@
},
"nixpkgs-2111": {
"locked": {
"lastModified": 1656782578,
"narHash": "sha256-1eMCBEqJplPotTo/SZ/t5HU6Sf2I8qKlZi9MX7jv9fw=",
"lastModified": 1659446231,
"narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "573603b7fdb9feb0eb8efc16ee18a015c667ab1b",
"rev": "eabc38219184cc3e04a974fe31857d8e0eac098d",
"type": "github"
},
"original": {
@ -342,11 +628,11 @@
},
"nixpkgs-2205": {
"locked": {
"lastModified": 1657876628,
"narHash": "sha256-URmf0O2cQ/3heg2DJOeLyU/JmfVMqG4X5t9crQXMaeY=",
"lastModified": 1672580127,
"narHash": "sha256-3lW3xZslREhJogoOkjeZtlBtvFMyxHku7I/9IVehhT8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "549d82bdd40f760a438c3c3497c1c61160f3de55",
"rev": "0874168639713f547c05947c76124f78441ea46c",
"type": "github"
},
"original": {
@ -356,6 +642,22 @@
"type": "github"
}
},
"nixpkgs-2211": {
"locked": {
"lastModified": 1675730325,
"narHash": "sha256-uNvD7fzO5hNlltNQUAFBPlcEjNG5Gkbhl/ROiX+GZU4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b7ce17b1ebf600a72178f6302c77b6382d09323f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-22.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
@ -366,18 +668,19 @@
"type": "github"
},
"original": {
"id": "nixpkgs",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "indirect"
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1657888067,
"narHash": "sha256-GnwJoFBTPfW3+mz7QEeJEEQ9OMHZOiIJ/qDhZxrlKh8=",
"lastModified": 1675758091,
"narHash": "sha256-7gFSQbSVAFUHtGCNHPF7mPc5CcqDk9M2+inlVPZSneg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "65fae659e31098ca4ac825a6fef26d890aaf3f4e",
"rev": "747927516efcb5e31ba03b7ff32f61f6d47e7d87",
"type": "github"
},
"original": {
@ -387,6 +690,68 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1653581809,
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1654807842,
"narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fc909087cc3386955f21b4665731dbdaceefb1d8",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1665087388,
"narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"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": {
@ -406,7 +771,10 @@
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"flake-utils": [
"haskell-nix",
"flake-utils"
],
"haskell-nix": "haskell-nix",
"nixpkgs": [
"haskell-nix",
@ -417,11 +785,11 @@
"stackage": {
"flake": false,
"locked": {
"lastModified": 1661925696,
"narHash": "sha256-eMM1dhdSv0AlLtD2cULJsLhJF4ZWdvpqRcCOw9DbXLI=",
"lastModified": 1677543037,
"narHash": "sha256-7CPQZZafTQiw7YL+a2KCamb9a3PU0do9iZKy1AaRkBo=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "575039e5410ef653e302d53938aa6df403e5a8b1",
"rev": "f4d29fa4403f45541d9f3993523df6027c21fe90",
"type": "github"
},
"original": {
@ -429,6 +797,113 @@
"repo": "stackage.nix",
"type": "github"
}
},
"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"
],
"microvm": [
"haskell-nix",
"tullia",
"std",
"blank"
],
"n2c": "n2c",
"nixago": "nixago",
"nixpkgs": "nixpkgs_4",
"nosys": "nosys",
"yants": "yants"
},
"locked": {
"lastModified": 1674526466,
"narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=",
"owner": "divnix",
"repo": "std",
"rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "std",
"type": "github"
}
},
"tullia": {
"inputs": {
"nix-nomad": "nix-nomad",
"nix2container": "nix2container",
"nixpkgs": [
"haskell-nix",
"nixpkgs"
],
"std": "std"
},
"locked": {
"lastModified": 1675695930,
"narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=",
"owner": "input-output-hk",
"repo": "tullia",
"rev": "621365f2c725608f381b3ad5b57afef389fd4c31",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "tullia",
"type": "github"
}
},
"utils": {
"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"
}
},
"yants": {
"inputs": {
"nixpkgs": [
"haskell-nix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1667096281,
"narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=",
"owner": "divnix",
"repo": "yants",
"rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "yants",
"type": "github"
}
}
},
"root": "root",

View File

@ -1,50 +1,52 @@
{
description = "Foliage is a tool to create custom Haskell package repositories, in a fully reproducible way.";
description =
"Foliage is a tool to create custom Haskell package repositories, in a fully reproducible way.";
inputs = {
nixpkgs.follows = "haskell-nix/nixpkgs-unstable";
haskell-nix.url = "github:input-output-hk/haskell.nix";
flake-utils.url = "github:numtide/flake-utils";
flake-utils.follows = "haskell-nix/flake-utils";
};
outputs = { self, nixpkgs, flake-utils, haskell-nix }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; inherit (haskell-nix) config; overlays = [haskell-nix.overlay]; };
project = pkgs.haskell-nix.cabalProject {
src = ./.;
compiler-nix-name = "ghc8107";
shell.tools = {
cabal = {};
hlint = {};
haskell-language-server = {};
flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
let
pkgs = import nixpkgs {
inherit system;
inherit (haskell-nix) config;
overlays = [ haskell-nix.overlay ];
};
shell.buildInputs = with pkgs; [
nixpkgs-fmt
fsatrace
];
modules = [{
packages.foliage.components.exes.foliage.dontStrip = false;
}];
};
in {
packages.default = project.foliage.components.exes.foliage;
devShell = pkgs.mkShell {
name = "foliage-dev-shell";
buildInputs = with pkgs; [
fsatrace
];
};
});
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;
project = pkgs-static-where-possible.haskell-nix.cabalProject' {
src = ./.;
compiler-nix-name = "ghc926";
};
flake = project.flake { };
in
flake // { packages.default = flake.packages."foliage:exe:foliage"; });
nixConfig = {
extra-substituters = [
"https://cache.iog.io"
"https://foliage.cachix.org"
"https://cache.zw3rk.com"
];
extra-trusted-public-keys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
"foliage.cachix.org-1:kAFyYLnk8JcRURWReWZCatM9v3Rk24F5wNMpEj14Q/g="
"loony-tools:pr9m4BkM/5/eSTZlkQyRt57Jz7OMBxNSUiMC4FkcNfk="
];
};
}

View File

@ -27,6 +27,7 @@ executable foliage
Foliage.Meta.Aeson
Foliage.Options
Foliage.Pages
Foliage.PreparePackageVersion
Foliage.PrepareSource
Foliage.PrepareSdist
Foliage.RemoteAsset
@ -34,13 +35,13 @@ executable foliage
Foliage.Time
Foliage.UpdateCabalFile
Foliage.Utils.Aeson
Foliage.Utils.GitHub
Network.URI.Orphans
default-language: Haskell2010
default-extensions:
ImportQualifiedPost LambdaCase NamedFieldPuns ViewPatterns
default-language: GHC2021
ghc-options: -Wall
ghc-options: -threaded
build-depends:
base >=4.14.3.0 && <4.18,
aeson >=2.0.3.0 && <2.2,

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>