{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}

-- | Copyright: (c) 2021 berberman
-- SPDX-License-Identifier: MIT
-- Maintainer: berberman <berberman@yandex.com>
-- Stability: experimental
-- Portability: portable
module NvFetcher.Core
  ( coreRules,
    generateNixSourceExpr,
  )
where

import Data.Coerce (coerce)
import Data.Text (Text)
import Development.Shake
import Development.Shake.Rule
import NeatInterpolation (trimming)
import NvFetcher.NixFetcher
import NvFetcher.Nvchecker
import NvFetcher.ShakeExtras
import NvFetcher.Types
import NvFetcher.Utils

-- | The core rule of nvchecker.
-- nvchecker rule and prefetch rule are wired here.
coreRules :: Rules ()
coreRules :: Rules ()
coreRules = do
  Rules ()
nvcheckerRule
  Rules ()
prefetchRule
  BuiltinLint (WithPackageKey Core) NixExpr
-> BuiltinIdentity (WithPackageKey Core) NixExpr
-> BuiltinRun (WithPackageKey Core) NixExpr
-> Rules ()
forall key value.
(RuleResult key ~ value, ShakeValue key, Typeable value,
 NFData value, Show value, Partial) =>
BuiltinLint key value
-> BuiltinIdentity key value -> BuiltinRun key value -> Rules ()
addBuiltinRule BuiltinLint (WithPackageKey Core) NixExpr
forall key value. BuiltinLint key value
noLint BuiltinIdentity (WithPackageKey Core) NixExpr
forall key value. BuiltinIdentity key value
noIdentity (BuiltinRun (WithPackageKey Core) NixExpr -> Rules ())
-> BuiltinRun (WithPackageKey Core) NixExpr -> Rules ()
forall a b. (a -> b) -> a -> b
$ \(WithPackageKey (Core
Core, PackageKey
pkg)) Maybe ByteString
mOld RunMode
mode -> case RunMode
mode of
    RunMode
RunDependenciesSame
      | Just ByteString
old <- Maybe ByteString
mOld,
        (NixExpr
expr, Version
_) <- ByteString -> (NixExpr, Version)
forall a. Binary a => ByteString -> a
decode' @(NixExpr, Version) ByteString
old ->
        RunResult NixExpr -> Action (RunResult NixExpr)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RunResult NixExpr -> Action (RunResult NixExpr))
-> RunResult NixExpr -> Action (RunResult NixExpr)
forall a b. (a -> b) -> a -> b
$ RunChanged -> ByteString -> NixExpr -> RunResult NixExpr
forall value. RunChanged -> ByteString -> value -> RunResult value
RunResult RunChanged
ChangedNothing ByteString
old NixExpr
expr
    RunMode
_ ->
      PackageKey -> Action (Maybe Package)
lookupPackage PackageKey
pkg Action (Maybe Package)
-> (Maybe Package -> Action (RunResult NixExpr))
-> Action (RunResult NixExpr)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Maybe Package
Nothing -> String -> Action (RunResult NixExpr)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Action (RunResult NixExpr))
-> String -> Action (RunResult NixExpr)
forall a b. (a -> b) -> a -> b
$ String
"Unkown package key: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PackageKey -> String
forall a. Show a => a -> String
show PackageKey
pkg
        Just Package {NixExpr
VersionSource
PackageFetcher
pfetcher :: Package -> PackageFetcher
pversion :: Package -> VersionSource
pname :: Package -> NixExpr
pfetcher :: PackageFetcher
pversion :: VersionSource
pname :: NixExpr
..} -> do
          (NvcheckerResult Version
version Maybe Version
mOldV) <- VersionSource -> PackageKey -> Action NvcheckerResult
checkVersion VersionSource
pversion PackageKey
pkg
          NixFetcher 'Prefetched
prefetched <- NixFetcher 'Fresh -> Action (NixFetcher 'Prefetched)
prefetch (NixFetcher 'Fresh -> Action (NixFetcher 'Prefetched))
-> NixFetcher 'Fresh -> Action (NixFetcher 'Prefetched)
forall a b. (a -> b) -> a -> b
$ PackageFetcher
pfetcher Version
version
          case Maybe Version
mOldV of
            Maybe Version
Nothing ->
              NixExpr -> Maybe Version -> Version -> Action ()
recordVersionChange NixExpr
pname Maybe Version
forall a. Maybe a
Nothing Version
version
            Just Version
old
              | Version
old Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
/= Version
version ->
                NixExpr -> Maybe Version -> Version -> Action ()
recordVersionChange NixExpr
pname (Version -> Maybe Version
forall a. a -> Maybe a
Just Version
old) Version
version
            Maybe Version
_ -> () -> Action ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
          let result :: NixExpr
result = NixExpr -> Version -> NixFetcher 'Prefetched -> NixExpr
gen NixExpr
pname Version
version NixFetcher 'Prefetched
prefetched
          RunResult NixExpr -> Action (RunResult NixExpr)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RunResult NixExpr -> Action (RunResult NixExpr))
-> RunResult NixExpr -> Action (RunResult NixExpr)
forall a b. (a -> b) -> a -> b
$ RunChanged -> ByteString -> NixExpr -> RunResult NixExpr
forall value. RunChanged -> ByteString -> value -> RunResult value
RunResult RunChanged
ChangedRecomputeDiff ((NixExpr, Version) -> ByteString
forall a. Binary a => a -> ByteString
encode' (NixExpr
result, Version
version)) NixExpr
result

-- | Run the core rule.
-- Given a package key, run nvchecker and then prefetch it,
-- resulting a nix source snippet like:
--
-- @@
-- feeluown-core = {
--     pname = "feeluown-core";
--     version = "3.7.7";
--     src = fetchurl {
--       sha256 = "06d3j39ff9znqxkhp9ly81lcgajkhg30hyqxy2809yn23xixg3x2";
--       url = "https://pypi.io/packages/source/f/feeluown/feeluown-3.7.7.tar.gz";
--     };
--   };
-- @@
generateNixSourceExpr :: PackageKey -> Action NixExpr
generateNixSourceExpr :: PackageKey -> Action NixExpr
generateNixSourceExpr PackageKey
k = WithPackageKey Core -> Action NixExpr
forall key value.
(Partial, RuleResult key ~ value, ShakeValue key,
 Typeable value) =>
key -> Action value
apply1 (WithPackageKey Core -> Action NixExpr)
-> WithPackageKey Core -> Action NixExpr
forall a b. (a -> b) -> a -> b
$ (Core, PackageKey) -> WithPackageKey Core
forall k. (k, PackageKey) -> WithPackageKey k
WithPackageKey (Core
Core, PackageKey
k)

gen :: PackageName -> Version -> NixFetcher Prefetched -> Text
gen :: NixExpr -> Version -> NixFetcher 'Prefetched -> NixExpr
gen NixExpr
name (Version -> NixExpr
coerce -> NixExpr
ver) (NixFetcher 'Prefetched -> NixExpr
forall a. ToNixExpr a => a -> NixExpr
toNixExpr -> NixExpr
srcP) =
  [trimming|
  $name = {
    pname = "$name";
    version = "$ver";
    src = $srcP;
  };
|]