{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

-- | Copyright: (c) 2021 berberman
-- SPDX-License-Identifier: MIT
-- Maintainer: berberman <berberman@yandex.com>
-- Stability: experimental
-- Portability: portable
--
-- This module mainly contains two things: 'PackageSet' and 'PkgDSL'.
-- NvFetcher accepts the former one -- a set of packages to produce nix sources expr;
-- the later one is used to construct a single package.
--
-- There are many combinators for defining packages. See the documentation of 'define' for example.
module NvFetcher.PackageSet
  ( -- * Package set
    PackageSetF,
    PackageSet,
    newPackage,
    purePackageSet,
    runPackageSet,

    -- * Package DSL

    -- ** Primitives
    PkgDSL (..),
    define,
    package,
    src,
    fetch,

    -- ** Two-in-one functions
    fromGitHub,
    fromPypi,

    -- ** Version sources
    sourceGitHub,
    sourceGit,
    sourcePypi,
    sourceAur,
    sourceArchLinux,
    sourceManual,
    sourceRepology,

    -- ** Fetchers
    fetchGitHub,
    fetchGitHubRelease,
    fetchPypi,
    fetchGit,
    fetchUrl,

    -- ** Miscellaneous
    Prod,
    Member,
    NotElem,
    coerce,
    liftIO,
  )
where

import Control.Monad.Free
import Control.Monad.IO.Class
import Data.Coerce (coerce)
import Data.Kind (Constraint, Type)
import Data.HashMap.Strict as HMap
import Data.Maybe (isJust)
import Data.Text (Text)
import GHC.TypeLits
import NvFetcher.NixFetcher
import NvFetcher.Types

--------------------------------------------------------------------------------

-- | Atomic terms of package set
data PackageSetF f
  = NewPackage !Package f
  | forall a. EmbedIO !(IO a) (a -> f)

instance Functor PackageSetF where
  fmap :: (a -> b) -> PackageSetF a -> PackageSetF b
fmap a -> b
f (NewPackage Package
p a
g) = Package -> b -> PackageSetF b
forall f. Package -> f -> PackageSetF f
NewPackage Package
p (b -> PackageSetF b) -> b -> PackageSetF b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
g
  fmap a -> b
f (EmbedIO IO a
action a -> a
g) = IO a -> (a -> b) -> PackageSetF b
forall f a. IO a -> (a -> f) -> PackageSetF f
EmbedIO IO a
action ((a -> b) -> PackageSetF b) -> (a -> b) -> PackageSetF b
forall a b. (a -> b) -> a -> b
$ a -> b
f (a -> b) -> (a -> a) -> a -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> a
g

-- | Package set is a monad equipped with two capabilities:
--
-- 1. Carry defined packages
-- 2. Run IO actions
--
-- Package set is evaluated be for shake runs.
-- Use 'newPackage' to add a new package, 'liftIO' to run an IO action.
type PackageSet = Free PackageSetF

instance MonadIO PackageSet where
  liftIO :: IO a -> PackageSet a
liftIO IO a
io = PackageSetF a -> PackageSet a
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (PackageSetF a -> PackageSet a) -> PackageSetF a -> PackageSet a
forall a b. (a -> b) -> a -> b
$ IO a -> (a -> a) -> PackageSetF a
forall f a. IO a -> (a -> f) -> PackageSetF f
EmbedIO IO a
io a -> a
forall a. a -> a
id

-- | Add a package to package set
newPackage ::
  PackageName ->
  VersionSource ->
  PackageFetcher ->
  PackageSet ()
newPackage :: PackageName -> VersionSource -> PackageFetcher -> PackageSet ()
newPackage PackageName
name VersionSource
source PackageFetcher
fetcher = PackageSetF () -> PackageSet ()
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (PackageSetF () -> PackageSet ())
-> PackageSetF () -> PackageSet ()
forall a b. (a -> b) -> a -> b
$ Package -> () -> PackageSetF ()
forall f. Package -> f -> PackageSetF f
NewPackage (PackageName -> VersionSource -> PackageFetcher -> Package
Package PackageName
name VersionSource
source PackageFetcher
fetcher) ()

-- | Add a list of packages into package set
purePackageSet :: [Package] -> PackageSet ()
purePackageSet :: [Package] -> PackageSet ()
purePackageSet = (Package -> PackageSet ()) -> [Package] -> PackageSet ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (PackageSetF () -> PackageSet ()
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (PackageSetF () -> PackageSet ())
-> (Package -> PackageSetF ()) -> Package -> PackageSet ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> () -> PackageSetF ())
-> () -> Package -> PackageSetF ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Package -> () -> PackageSetF ()
forall f. Package -> f -> PackageSetF f
NewPackage ())

-- | Run package set into a set of packages
--
-- Throws exception as more then one packages with the same name
-- are defined
runPackageSet :: PackageSet () -> IO (HashMap PackageKey Package)
runPackageSet :: PackageSet () -> IO (HashMap PackageKey Package)
runPackageSet = \case
  Free (NewPackage Package
p PackageSet ()
g) ->
    PackageSet () -> IO (HashMap PackageKey Package)
runPackageSet PackageSet ()
g IO (HashMap PackageKey Package)
-> (HashMap PackageKey Package -> IO (HashMap PackageKey Package))
-> IO (HashMap PackageKey Package)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \HashMap PackageKey Package
m ->
      if Maybe Package -> Bool
forall a. Maybe a -> Bool
isJust (PackageKey -> HashMap PackageKey Package -> Maybe Package
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HMap.lookup (PackageName -> PackageKey
PackageKey (PackageName -> PackageKey) -> PackageName -> PackageKey
forall a b. (a -> b) -> a -> b
$ Package -> PackageName
pname Package
p) HashMap PackageKey Package
m)
        then String -> IO (HashMap PackageKey Package)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO (HashMap PackageKey Package))
-> String -> IO (HashMap PackageKey Package)
forall a b. (a -> b) -> a -> b
$ String
"Duplicate package name: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PackageName -> String
forall a. Show a => a -> String
show (Package -> PackageName
pname Package
p)
        else HashMap PackageKey Package -> IO (HashMap PackageKey Package)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (HashMap PackageKey Package -> IO (HashMap PackageKey Package))
-> HashMap PackageKey Package -> IO (HashMap PackageKey Package)
forall a b. (a -> b) -> a -> b
$ PackageKey
-> Package
-> HashMap PackageKey Package
-> HashMap PackageKey Package
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HMap.insert (PackageName -> PackageKey
PackageKey (PackageName -> PackageKey) -> PackageName -> PackageKey
forall a b. (a -> b) -> a -> b
$ Package -> PackageName
pname Package
p) Package
p HashMap PackageKey Package
m
  Free (EmbedIO IO a
action a -> PackageSet ()
g) -> IO a
action IO a
-> (a -> IO (HashMap PackageKey Package))
-> IO (HashMap PackageKey Package)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= PackageSet () -> IO (HashMap PackageKey Package)
runPackageSet (PackageSet () -> IO (HashMap PackageKey Package))
-> (a -> PackageSet ()) -> a -> IO (HashMap PackageKey Package)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> PackageSet ()
g
  Pure ()
_ -> HashMap PackageKey Package -> IO (HashMap PackageKey Package)
forall (f :: * -> *) a. Applicative f => a -> f a
pure HashMap PackageKey Package
forall a. Monoid a => a
mempty

--------------------------------------------------------------------------------

-- | Simple HList
data Prod (r :: [Type]) where
  Nil :: Prod '[]
  Cons :: !x -> Prod xs -> Prod (x ': xs)

-- | Project elements from 'Prod'
class Member (a :: Type) (r :: [Type]) where
  proj :: Prod r -> a

instance {-# OVERLAPPING #-} NotElem x xs => Member x (x ': xs) where
  proj :: Prod (x : xs) -> x
proj (Cons x
x Prod xs
_) = x
x
x

instance Member x xs => Member x (_y ': xs) where
  proj :: Prod (_y : xs) -> x
proj (Cons x
_ Prod xs
r) = Prod xs -> x
forall a (r :: [*]). Member a r => Prod r -> a
proj Prod xs
r

instance TypeError (ShowType x :<>: 'Text " is undefined") => Member x '[] where
  proj :: Prod '[] -> x
proj = Prod '[] -> x
forall a. HasCallStack => a
undefined

-- | Constraint for producing error messages
type family NotElem (x :: Type) (xs :: [Type]) :: Constraint where
  NotElem x (x ': xs) = TypeError (ShowType x :<>: 'Text " is defined more than one times")
  NotElem x (_ ': xs) = NotElem x xs
  NotElem x '[] = ()

--------------------------------------------------------------------------------

-- | A tagless final style DSL for constructing packages
class PkgDSL f where
  new :: f PackageName -> f (Prod '[PackageName])
  andThen :: f (Prod r) -> f a -> f (Prod (a ': r))
  end :: (Member PackageName r, Member VersionSource r, Member PackageFetcher r) => f (Prod r) -> f ()

instance PkgDSL PackageSet where
  new :: PackageSet PackageName -> PackageSet (Prod '[PackageName])
new PackageSet PackageName
e = do
    PackageName
name <- PackageSet PackageName
e
    Prod '[PackageName] -> PackageSet (Prod '[PackageName])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Prod '[PackageName] -> PackageSet (Prod '[PackageName]))
-> Prod '[PackageName] -> PackageSet (Prod '[PackageName])
forall a b. (a -> b) -> a -> b
$ PackageName -> Prod '[] -> Prod '[PackageName]
forall x (xs :: [*]). x -> Prod xs -> Prod (x : xs)
Cons PackageName
name Prod '[]
Nil
  andThen :: PackageSet (Prod r) -> PackageSet a -> PackageSet (Prod (a : r))
andThen PackageSet (Prod r)
e PackageSet a
e' = do
    Prod r
p <- PackageSet (Prod r)
e
    a
x <- PackageSet a
e'
    Prod (a : r) -> PackageSet (Prod (a : r))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Prod (a : r) -> PackageSet (Prod (a : r)))
-> Prod (a : r) -> PackageSet (Prod (a : r))
forall a b. (a -> b) -> a -> b
$ a -> Prod r -> Prod (a : r)
forall x (xs :: [*]). x -> Prod xs -> Prod (x : xs)
Cons a
x Prod r
p
  end :: PackageSet (Prod r) -> PackageSet ()
end PackageSet (Prod r)
e = do
    Prod r
p <- PackageSet (Prod r)
e
    PackageName -> VersionSource -> PackageFetcher -> PackageSet ()
newPackage (Prod r -> PackageName
forall a (r :: [*]). Member a r => Prod r -> a
proj Prod r
p) (Prod r -> VersionSource
forall a (r :: [*]). Member a r => Prod r -> a
proj Prod r
p) (Prod r -> PackageFetcher
forall a (r :: [*]). Member a r => Prod r -> a
proj Prod r
p)

-- | 'PkgDSL' version of 'newPackage'
--
-- Example:
--
-- @
-- define $ package "nvfetcher-git" `sourceGit` "nvfetcher" `fetchGitHub` ("berberman", "nvfetcher")
-- @
define ::
  ( Member PackageName r,
    Member VersionSource r,
    Member PackageFetcher r
  ) =>
  PackageSet (Prod r) ->
  PackageSet ()
define :: PackageSet (Prod r) -> PackageSet ()
define = PackageSet (Prod r) -> PackageSet ()
forall (f :: * -> *) (r :: [*]).
(PkgDSL f, Member PackageName r, Member VersionSource r,
 Member PackageFetcher r) =>
f (Prod r) -> f ()
end

-- | Start chaining with the name of package to define
package :: PackageName -> PackageSet (Prod '[PackageName])
package :: PackageName -> PackageSet (Prod '[PackageName])
package = PackageSet PackageName -> PackageSet (Prod '[PackageName])
forall (f :: * -> *).
PkgDSL f =>
f PackageName -> f (Prod '[PackageName])
new (PackageSet PackageName -> PackageSet (Prod '[PackageName]))
-> (PackageName -> PackageSet PackageName)
-> PackageName
-> PackageSet (Prod '[PackageName])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> PackageSet PackageName
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | Attach version sources
src :: PackageSet (Prod r) -> VersionSource -> PackageSet (Prod (VersionSource ': r))
src :: PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src = ((Free PackageSetF VersionSource
 -> PackageSet (Prod (VersionSource : r)))
-> (VersionSource -> Free PackageSetF VersionSource)
-> VersionSource
-> PackageSet (Prod (VersionSource : r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VersionSource -> Free PackageSetF VersionSource
forall (f :: * -> *) a. Applicative f => a -> f a
pure) ((Free PackageSetF VersionSource
  -> PackageSet (Prod (VersionSource : r)))
 -> VersionSource -> PackageSet (Prod (VersionSource : r)))
-> (PackageSet (Prod r)
    -> Free PackageSetF VersionSource
    -> PackageSet (Prod (VersionSource : r)))
-> PackageSet (Prod r)
-> VersionSource
-> PackageSet (Prod (VersionSource : r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageSet (Prod r)
-> Free PackageSetF VersionSource
-> PackageSet (Prod (VersionSource : r))
forall (f :: * -> *) (r :: [*]) a.
PkgDSL f =>
f (Prod r) -> f a -> f (Prod (a : r))
andThen

-- | Attach fetchers
fetch ::
  PackageSet (Prod r) ->
  PackageFetcher ->
  PackageSet (Prod (PackageFetcher ': r))
fetch :: PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
fetch = ((Free PackageSetF PackageFetcher
 -> PackageSet (Prod (PackageFetcher : r)))
-> (PackageFetcher -> Free PackageSetF PackageFetcher)
-> PackageFetcher
-> PackageSet (Prod (PackageFetcher : r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageFetcher -> Free PackageSetF PackageFetcher
forall (f :: * -> *) a. Applicative f => a -> f a
pure) ((Free PackageSetF PackageFetcher
  -> PackageSet (Prod (PackageFetcher : r)))
 -> PackageFetcher -> PackageSet (Prod (PackageFetcher : r)))
-> (PackageSet (Prod r)
    -> Free PackageSetF PackageFetcher
    -> PackageSet (Prod (PackageFetcher : r)))
-> PackageSet (Prod r)
-> PackageFetcher
-> PackageSet (Prod (PackageFetcher : r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageSet (Prod r)
-> Free PackageSetF PackageFetcher
-> PackageSet (Prod (PackageFetcher : r))
forall (f :: * -> *) (r :: [*]) a.
PkgDSL f =>
f (Prod r) -> f a -> f (Prod (a : r))
andThen

--------------------------------------------------------------------------------

-- | A synonym of 'fetchGitHub' and 'sourceGitHub'
fromGitHub ::
  PackageSet (Prod r) ->
  (Text, Text) ->
  PackageSet
    (Prod (PackageFetcher : VersionSource : r))
fromGitHub :: PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (PackageFetcher : VersionSource : r))
fromGitHub PackageSet (Prod r)
e (PackageName, PackageName)
p = PackageSet (Prod (VersionSource : r))
-> (PackageName, PackageName)
-> PackageSet (Prod (PackageFetcher : VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (PackageFetcher : r))
fetchGitHub (PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (VersionSource : r))
sourceGitHub PackageSet (Prod r)
e (PackageName, PackageName)
p) (PackageName, PackageName)
p

-- | A synonym of 'fetchPypi' and 'sourcePypi'
fromPypi ::
  PackageSet (Prod r) ->
  Text ->
  PackageSet
    (Prod (PackageFetcher : VersionSource : r))
fromPypi :: PackageSet (Prod r)
-> PackageName
-> PackageSet (Prod (PackageFetcher : VersionSource : r))
fromPypi PackageSet (Prod r)
e PackageName
p = PackageSet (Prod (VersionSource : r))
-> PackageName
-> PackageSet (Prod (PackageFetcher : VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (PackageFetcher : r))
fetchPypi (PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
sourcePypi PackageSet (Prod r)
e PackageName
p) PackageName
p

--------------------------------------------------------------------------------

-- | This package follows the latest github release
sourceGitHub ::
  PackageSet (Prod r) ->
  -- | owner and repo
  (Text, Text) ->
  PackageSet (Prod (VersionSource : r))
sourceGitHub :: PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (VersionSource : r))
sourceGitHub PackageSet (Prod r)
e (PackageName
owner, PackageName
repo) = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e (VersionSource -> PackageSet (Prod (VersionSource : r)))
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall a b. (a -> b) -> a -> b
$ PackageName -> PackageName -> VersionSource
GitHubRelease PackageName
owner PackageName
repo

-- | This package follows the latest git commit
sourceGit ::
  PackageSet (Prod r) ->
  -- | git url
  Text ->
  PackageSet (Prod (VersionSource : r))
sourceGit :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
sourceGit PackageSet (Prod r)
e PackageName
vurl = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e Git :: PackageName -> VersionSource
Git {PackageName
vurl :: PackageName
vurl :: PackageName
..}

-- | This package follows the latest pypi release
sourcePypi ::
  PackageSet (Prod r) ->
  -- | pypi name
  Text ->
  PackageSet (Prod (VersionSource : r))
sourcePypi :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
sourcePypi PackageSet (Prod r)
e PackageName
pypi = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e Pypi :: PackageName -> VersionSource
Pypi {PackageName
pypi :: PackageName
pypi :: PackageName
..}

-- | This package follows the version of an Arch Linux package
sourceArchLinux ::
  PackageSet (Prod r) ->
  -- | package name in Arch Linux repo
  Text ->
  PackageSet (Prod (VersionSource : r))
sourceArchLinux :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
sourceArchLinux PackageSet (Prod r)
e PackageName
archpkg = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e ArchLinux :: PackageName -> VersionSource
ArchLinux {PackageName
archpkg :: PackageName
archpkg :: PackageName
..}

-- | This package follows the version of an Aur package
sourceAur ::
  PackageSet (Prod r) ->
  -- | package name in Aur
  Text ->
  PackageSet (Prod (VersionSource : r))
sourceAur :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
sourceAur PackageSet (Prod r)
e PackageName
aur = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e Aur :: PackageName -> VersionSource
Aur {PackageName
aur :: PackageName
aur :: PackageName
..}

-- | This package follows a pinned version
sourceManual ::
  PackageSet (Prod r) ->
  Text ->
  PackageSet (Prod (VersionSource : r))
sourceManual :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (VersionSource : r))
sourceManual PackageSet (Prod r)
e PackageName
manual = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e Manual :: PackageName -> VersionSource
Manual {PackageName
manual :: PackageName
manual :: PackageName
..}

-- | This package follows the version of a repology package
sourceRepology ::
  PackageSet (Prod r) ->
  -- | repology project name and repo
  (Text, Text) ->
  PackageSet (Prod (VersionSource : r))
sourceRepology :: PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (VersionSource : r))
sourceRepology PackageSet (Prod r)
e (PackageName
project, PackageName
repo) = PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall (r :: [*]).
PackageSet (Prod r)
-> VersionSource -> PackageSet (Prod (VersionSource : r))
src PackageSet (Prod r)
e (VersionSource -> PackageSet (Prod (VersionSource : r)))
-> VersionSource -> PackageSet (Prod (VersionSource : r))
forall a b. (a -> b) -> a -> b
$ PackageName -> PackageName -> VersionSource
Repology PackageName
project PackageName
repo

--------------------------------------------------------------------------------

-- | This package is fetched from a github repo
fetchGitHub ::
  PackageSet (Prod r) ->
  -- | owner and repo
  (Text, Text) ->
  PackageSet (Prod (PackageFetcher : r))
fetchGitHub :: PackageSet (Prod r)
-> (PackageName, PackageName)
-> PackageSet (Prod (PackageFetcher : r))
fetchGitHub PackageSet (Prod r)
e (PackageName, PackageName)
p = PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
fetch PackageSet (Prod r)
e (PackageFetcher -> PackageSet (Prod (PackageFetcher : r)))
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall a b. (a -> b) -> a -> b
$ (PackageName, PackageName) -> PackageFetcher
gitHubFetcher (PackageName, PackageName)
p

-- | This package is fetched from a file in github release
fetchGitHubRelease ::
  PackageSet (Prod r) ->
  -- | owner, repo, and file name
  (Text, Text, Text) ->
  PackageSet (Prod (PackageFetcher : r))
fetchGitHubRelease :: PackageSet (Prod r)
-> (PackageName, PackageName, PackageName)
-> PackageSet (Prod (PackageFetcher : r))
fetchGitHubRelease PackageSet (Prod r)
e (PackageName
owner, PackageName
repo, PackageName
fp) = PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
fetch PackageSet (Prod r)
e (PackageFetcher -> PackageSet (Prod (PackageFetcher : r)))
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall a b. (a -> b) -> a -> b
$ (PackageName, PackageName) -> PackageName -> PackageFetcher
gitHubReleaseFetcher (PackageName
owner, PackageName
repo) PackageName
fp

-- | This package is fetched from pypi
fetchPypi ::
  PackageSet (Prod r) ->
  -- | pypi name
  Text ->
  PackageSet (Prod (PackageFetcher : r))
fetchPypi :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (PackageFetcher : r))
fetchPypi PackageSet (Prod r)
e = PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
fetch PackageSet (Prod r)
e (PackageFetcher -> PackageSet (Prod (PackageFetcher : r)))
-> (PackageName -> PackageFetcher)
-> PackageName
-> PackageSet (Prod (PackageFetcher : r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> PackageFetcher
pypiFetcher

-- | This package is fetched from git
fetchGit ::
  PackageSet (Prod r) ->
  -- | git url
  Text ->
  PackageSet (Prod (PackageFetcher : r))
fetchGit :: PackageSet (Prod r)
-> PackageName -> PackageSet (Prod (PackageFetcher : r))
fetchGit PackageSet (Prod r)
e = PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
fetch PackageSet (Prod r)
e (PackageFetcher -> PackageSet (Prod (PackageFetcher : r)))
-> (PackageName -> PackageFetcher)
-> PackageName
-> PackageSet (Prod (PackageFetcher : r))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageName -> PackageFetcher
gitFetcher

-- | This package is fetched from url
fetchUrl ::
  PackageSet (Prod r) ->
  -- | url, given a specific version
  (Version -> Text) ->
  PackageSet (Prod (PackageFetcher : r))
fetchUrl :: PackageSet (Prod r)
-> (Version -> PackageName)
-> PackageSet (Prod (PackageFetcher : r))
fetchUrl PackageSet (Prod r)
e Version -> PackageName
f = PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
forall (r :: [*]).
PackageSet (Prod r)
-> PackageFetcher -> PackageSet (Prod (PackageFetcher : r))
fetch PackageSet (Prod r)
e (PackageName -> NixFetcher 'Fresh
urlFetcher (PackageName -> NixFetcher 'Fresh)
-> (Version -> PackageName) -> PackageFetcher
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> PackageName
f)

--------------------------------------------------------------------------------