{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ViewPatterns #-}
module NvFetcher.NixExpr
( NixExpr,
ToNixExpr (..),
fetcherToDrv,
)
where
import Data.Coerce (coerce)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HMap
import qualified Data.List.NonEmpty as NE
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import NeatInterpolation (trimming)
import NvFetcher.Types
import NvFetcher.Utils (quote, quoteIfNeeds)
class ToNixExpr a where
toNixExpr :: a -> NixExpr
instance ToNixExpr (NixFetcher Fetched) where
toNixExpr :: NixFetcher 'Fetched -> Text
toNixExpr = NixFetcher 'Fetched -> Text
nixFetcher
instance ToNixExpr Bool where
toNixExpr :: Bool -> Text
toNixExpr Bool
True = Text
"true"
toNixExpr Bool
False = Text
"false"
instance ToNixExpr a => ToNixExpr [a] where
toNixExpr :: [a] -> Text
toNixExpr [a]
xs = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Text
acc a
x -> Text
acc forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> forall a. ToNixExpr a => a -> Text
toNixExpr a
x) Text
"[" [a]
xs forall a. Semigroup a => a -> a -> a
<> Text
" ]"
instance ToNixExpr a => ToNixExpr (NE.NonEmpty a) where
toNixExpr :: NonEmpty a -> Text
toNixExpr = forall a. ToNixExpr a => a -> Text
toNixExpr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. NonEmpty a -> [a]
NE.toList
instance {-# OVERLAPS #-} ToNixExpr String where
toNixExpr :: String -> Text
toNixExpr = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show
instance ToNixExpr NixExpr where
toNixExpr :: Text -> Text
toNixExpr = forall a. a -> a
id
instance ToNixExpr Version where
toNixExpr :: Version -> Text
toNixExpr = coerce :: forall a b. Coercible a b => a -> b
coerce
nixFetcher :: NixFetcher Fetched -> NixExpr
nixFetcher :: NixFetcher 'Fetched -> Text
nixFetcher = \case
FetchGit
{ _sha256 :: forall (k :: FetchStatus). NixFetcher k -> FetchResult Checksum k
_sha256 = coerce :: forall a b. Coercible a b => a -> b
coerce Text -> Text
quote -> Text
sha256,
_rev :: forall (k :: FetchStatus). NixFetcher k -> Version
_rev = Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
rev,
_fetchSubmodules :: forall (k :: FetchStatus). NixFetcher k -> Bool
_fetchSubmodules = forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
fetchSubmodules,
_deepClone :: forall (k :: FetchStatus). NixFetcher k -> Bool
_deepClone = forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
deepClone,
_leaveDotGit :: forall (k :: FetchStatus). NixFetcher k -> Bool
_leaveDotGit = forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
leaveDotGit,
_furl :: forall (k :: FetchStatus). NixFetcher k -> Text
_furl = Text -> Text
quote -> Text
url,
_name :: forall (k :: FetchStatus). NixFetcher k -> Maybe Text
_name = Maybe Text -> Text
nameField -> Text
n
} ->
[trimming|
fetchgit {
url = $url;
rev = $rev;
fetchSubmodules = $fetchSubmodules;
deepClone = $deepClone;
leaveDotGit = $leaveDotGit;$n
sha256 = $sha256;
}
|]
FetchGitHub
{ _sha256 :: forall (k :: FetchStatus). NixFetcher k -> FetchResult Checksum k
_sha256 = coerce :: forall a b. Coercible a b => a -> b
coerce Text -> Text
quote -> Text
sha256,
_rev :: forall (k :: FetchStatus). NixFetcher k -> Version
_rev = Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
rev,
_fetchSubmodules :: forall (k :: FetchStatus). NixFetcher k -> Bool
_fetchSubmodules = forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
fetchSubmodules,
_deepClone :: forall (k :: FetchStatus). NixFetcher k -> Bool
_deepClone = forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
deepClone,
_leaveDotGit :: forall (k :: FetchStatus). NixFetcher k -> Bool
_leaveDotGit = forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
leaveDotGit,
_fowner :: forall (k :: FetchStatus). NixFetcher k -> Text
_fowner = Text -> Text
quote -> Text
owner,
_frepo :: forall (k :: FetchStatus). NixFetcher k -> Text
_frepo = Text -> Text
quote -> Text
repo,
_name :: forall (k :: FetchStatus). NixFetcher k -> Maybe Text
_name = Maybe Text -> Text
nameField -> Text
n
} ->
if (Text
deepClone forall a. Eq a => a -> a -> Bool
== Text
"true") Bool -> Bool -> Bool
|| (Text
leaveDotGit forall a. Eq a => a -> a -> Bool
== Text
"true")
then
[trimming|
fetchFromGitHub {
owner = $owner;
repo = $repo;
rev = $rev;
fetchSubmodules = $fetchSubmodules;
deepClone = $deepClone;
leaveDotGit = $leaveDotGit;$n
sha256 = $sha256;
}
|]
else
[trimming|
fetchFromGitHub {
owner = $owner;
repo = $repo;
rev = $rev;
fetchSubmodules = $fetchSubmodules;$n
sha256 = $sha256;
}
|]
(FetchUrl (Text -> Text
quote -> Text
url) (Maybe Text -> Text
nameField -> Text
n) (coerce :: forall a b. Coercible a b => a -> b
coerce Text -> Text
quote -> Text
sha256)) ->
[trimming|
fetchurl {
url = $url;$n
sha256 = $sha256;
}
|]
(FetchTarball (Text -> Text
quote -> Text
url) (coerce :: forall a b. Coercible a b => a -> b
coerce Text -> Text
quote -> Text
sha256)) ->
[trimming|
fetchTarball {
url = $url;
sha256 = $sha256;
}
|]
FetchDocker
{ _imageName :: forall (k :: FetchStatus). NixFetcher k -> Text
_imageName = Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
imageName,
_imageTag :: forall (k :: FetchStatus). NixFetcher k -> Text
_imageTag = Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
imageTag,
_imageDigest :: forall (k :: FetchStatus).
NixFetcher k -> FetchResult ContainerDigest k
_imageDigest = ContainerDigest (Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
imageDigest),
_sha256 :: forall (k :: FetchStatus). NixFetcher k -> FetchResult Checksum k
_sha256 = coerce :: forall a b. Coercible a b => a -> b
coerce Text -> Text
quote -> Text
sha256,
_fos :: forall (k :: FetchStatus). NixFetcher k -> Maybe Text
_fos = Text -> Maybe Text -> Text
optionalStr Text
"os" -> Text
os,
_farch :: forall (k :: FetchStatus). NixFetcher k -> Maybe Text
_farch = Text -> Maybe Text -> Text
optionalStr Text
"arch" -> Text
arch,
_finalImageName :: forall (k :: FetchStatus). NixFetcher k -> Maybe Text
_finalImageName = Text -> Maybe Text -> Text
optionalStr Text
"finalImageName" -> Text
finalImageName,
_finalImageTag :: forall (k :: FetchStatus). NixFetcher k -> Maybe Text
_finalImageTag = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
imageTag (Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToNixExpr a => a -> Text
toNixExpr) -> Text
finalImageTag,
_tlsVerify :: forall (k :: FetchStatus). NixFetcher k -> Maybe Bool
_tlsVerify = forall {a}. ToNixExpr a => Text -> Maybe a -> Text
optionalField Text
"tlsVerify" -> Text
tlsVerify
} ->
[trimming|
dockerTools.pullImage {
imageName = $imageName;
imageDigest = $imageDigest;
sha256 = $sha256;
finalImageTag = $finalImageTag;$os$arch$finalImageName$tlsVerify
}
|]
where
optionalField :: Text -> Maybe a -> Text
optionalField Text
n = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\a
x -> Text
"\n" forall a. Semigroup a => a -> a -> a
<> Text
n forall a. Semigroup a => a -> a -> a
<> Text
" = " forall a. Semigroup a => a -> a -> a
<> forall a. ToNixExpr a => a -> Text
toNixExpr a
x forall a. Semigroup a => a -> a -> a
<> Text
";")
optionalStr :: Text -> Maybe Text -> Text
optionalStr Text
n = forall {a}. ToNixExpr a => Text -> Maybe a -> Text
optionalField Text
n forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Text
quote
nameField :: Maybe Text -> Text
nameField = Text -> Maybe Text -> Text
optionalStr Text
"name"
fetcherToDrv :: NixFetcher Fetched -> Text -> NixExpr
fetcherToDrv :: NixFetcher 'Fetched -> Text -> Text
fetcherToDrv (forall a. ToNixExpr a => a -> Text
toNixExpr -> Text
fetcherExpr) (Text -> Text
quote -> Text
drvName) =
[trimming|
with import <nixpkgs> { };
stdenv.mkDerivation {
name = $drvName;
src = $fetcherExpr;
nativeBuildInputs = [ unzip ];
dontBuild = true;
installPhase = ''
mkdir $$out
cp -r * $$out
'';
}
|]
instance ToNixExpr PackageResult where
toNixExpr :: PackageResult -> Text
toNixExpr PackageResult {Maybe Text
Maybe (HashMap String (Text, HashMap Text Checksum))
Maybe (HashMap String Text)
Maybe (HashMap Text Text)
Text
UseStaleVersion
NixFetcher 'Fetched
NvcheckerResult
_prgitdate :: PackageResult -> Maybe Text
_prpinned :: PackageResult -> UseStaleVersion
_prcargolock :: PackageResult
-> Maybe (HashMap String (Text, HashMap Text Checksum))
_prextract :: PackageResult -> Maybe (HashMap String Text)
_prpassthru :: PackageResult -> Maybe (HashMap Text Text)
_prfetched :: PackageResult -> NixFetcher 'Fetched
_prversion :: PackageResult -> NvcheckerResult
_prname :: PackageResult -> Text
_prgitdate :: Maybe Text
_prpinned :: UseStaleVersion
_prcargolock :: Maybe (HashMap String (Text, HashMap Text Checksum))
_prextract :: Maybe (HashMap String Text)
_prpassthru :: Maybe (HashMap Text Text)
_prfetched :: NixFetcher 'Fetched
_prversion :: NvcheckerResult
_prname :: Text
..} =
[trimming|
$name = {
pname = $nameString;
version = $version;
src = $src;$appending
};
|]
where
name :: Text
name = Text -> Text
quoteIfNeeds Text
_prname
nameString :: Text
nameString = Text -> Text
quote Text
_prname
version :: Text
version = Text -> Text
quote forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. NvcheckerResult -> Version
nvNow forall a b. (a -> b) -> a -> b
$ NvcheckerResult
_prversion
src :: Text
src = forall a. ToNixExpr a => a -> Text
toNixExpr NixFetcher 'Fetched
_prfetched
extract :: Text
extract =
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
Text
""
( \HashMap String Text
ex ->
[Text] -> Text
T.unlines
[ Text -> Text
quoteIfNeeds (String -> Text
T.pack String
name)
forall a. Semigroup a => a -> a -> a
<> Text
" = builtins.readFile "
forall a. Semigroup a => a -> a -> a
<> Text
fp
forall a. Semigroup a => a -> a -> a
<> Text
";"
| (String
name, Text
fp) <- forall k v. HashMap k v -> [(k, v)]
HMap.toList HashMap String Text
ex
]
)
Maybe (HashMap String Text)
_prextract
cargo :: Text
cargo = forall a. a -> Maybe a -> a
fromMaybe Text
"" forall a b. (a -> b) -> a -> b
$ do
HashMap String (Text, HashMap Text Checksum)
cargoLocks <- Maybe (HashMap String (Text, HashMap Text Checksum))
_prcargolock
let depsSnippet :: HashMap Text Checksum -> Text
depsSnippet (HashMap Text Checksum
deps :: HashMap Text Checksum) =
[Text] -> Text
T.unlines
[ Text -> Text
quoteIfNeeds Text
name
forall a. Semigroup a => a -> a -> a
<> Text
" = "
forall a. Semigroup a => a -> a -> a
<> Text -> Text
quote (coerce :: forall a b. Coercible a b => a -> b
coerce Checksum
sum)
forall a. Semigroup a => a -> a -> a
<> Text
";"
| (Text
name, Checksum
sum) <- forall k v. HashMap k v -> [(k, v)]
HMap.toList HashMap Text Checksum
deps
]
lockSnippet :: (String, (Text, HashMap Text Checksum)) -> Text
lockSnippet ((String -> Text
T.pack -> Text
fp) :: FilePath, (Text
nixFP :: NixExpr, HashMap Text Checksum
deps :: HashMap Text Checksum)) =
let hashes :: Text
hashes = HashMap Text Checksum -> Text
depsSnippet HashMap Text Checksum
deps
in [trimming|
cargoLock."$fp" = {
lockFile = $nixFP;
outputHashes = {
$hashes
};
};
|]
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.unlines forall a b. (a -> b) -> a -> b
$ (String, (Text, HashMap Text Checksum)) -> Text
lockSnippet forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall k v. HashMap k v -> [(k, v)]
HMap.toList HashMap String (Text, HashMap Text Checksum)
cargoLocks
passthru :: Text
passthru =
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
Text
""
( \HashMap Text Text
pt ->
[Text] -> Text
T.unlines
[ Text -> Text
quoteIfNeeds Text
k
forall a. Semigroup a => a -> a -> a
<> Text
" = "
forall a. Semigroup a => a -> a -> a
<> Text
v
forall a. Semigroup a => a -> a -> a
<> Text
";"
| (Text
k, Text -> Text
quote -> Text
v) <- forall k v. HashMap k v -> [(k, v)]
HMap.toList HashMap Text Text
pt
]
)
Maybe (HashMap Text Text)
_prpassthru
date :: Text
date = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (\Text
d -> Text
"date = " forall a. Semigroup a => a -> a -> a
<> Text -> Text
quote Text
d forall a. Semigroup a => a -> a -> a
<> Text
";") Maybe Text
_prgitdate
joined :: Text
joined = Text
extract forall a. Semigroup a => a -> a -> a
<> Text
cargo forall a. Semigroup a => a -> a -> a
<> Text
passthru forall a. Semigroup a => a -> a -> a
<> Text
date
appending :: Text
appending = if Text -> Bool
T.null Text
joined then Text
"" else Text
"\n" forall a. Semigroup a => a -> a -> a
<> Text
joined