nvfetcher-0.4.0.0: app/Config/PackageFetcher.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}
module Config.PackageFetcher (fetcherCodec) where
import Data.Coerce (coerce)
import Data.Default (Default, def)
import Data.Foldable (asum)
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import GHC.Generics (Generic)
import Lens.Micro
import Lens.Micro.Extras (view)
import NvFetcher.NixFetcher
import NvFetcher.Types
import NvFetcher.Types.Lens
import Toml
unsupportError :: a
unsupportError = error "serialization is unsupported"
fetcherCodec :: TomlCodec PackageFetcher
fetcherCodec =
asum
[ gitHubCodec,
pypiCodec,
openVsxCodec,
vscodeMarketplaceCodec,
gitCodec,
urlCodec
]
--------------------------------------------------------------------------------
data GitOptions = GitOptions
{ goDeepClone :: Maybe Bool,
goFetchSubmodules :: Maybe Bool,
goLeaveDotGit :: Maybe Bool
}
deriving (Eq, Generic, Default)
gitOptionsCodec :: TomlCodec GitOptions
gitOptionsCodec =
GitOptions
<$> dioptional (bool "git.deepClone") .= goDeepClone
<*> dioptional (bool "git.fetchSubmodules") .= goFetchSubmodules
<*> dioptional (bool "git.leaveDotGit") .= goLeaveDotGit
_GitOptions :: Traversal' (NixFetcher f) GitOptions
_GitOptions f x@FetchGit {..} =
( \GitOptions {..} ->
x
& deepClone .~ fromMaybe False goDeepClone
& fetchSubmodules .~ fromMaybe False goFetchSubmodules
& leaveDotGit .~ fromMaybe False goLeaveDotGit
)
<$> f (GitOptions (Just _deepClone) (Just _fetchSubmodules) (Just _leaveDotGit))
_GitOptions _ x@FetchUrl {} = pure x
--------------------------------------------------------------------------------
gitHubICodec :: TomlCodec PackageFetcher
gitHubICodec =
textBy
unsupportError
( \t -> case T.split (== '/') t of
[owner, repo] -> Right $ gitHubFetcher (owner, repo)
_ -> Left "unexpected github fetcher: it should be something like [owner]/[repo]"
)
"fetch.github"
gitHubCodec :: TomlCodec PackageFetcher
gitHubCodec =
dimap
( \f -> let fake = f "$ver" in (f, fromMaybe def $ fake ^? _GitOptions)
)
(\(f, g) v -> f v & _GitOptions .~ g)
$ (,) <$> gitHubICodec .= view _1 <*> gitOptionsCodec .= view _2
--------------------------------------------------------------------------------
gitICodec :: TomlCodec PackageFetcher
gitICodec =
textBy
unsupportError
(Right . gitFetcher)
"fetch.git"
gitCodec :: TomlCodec PackageFetcher
gitCodec =
dimap
( \f -> let fake = f "$ver" in (f, fromMaybe def $ fake ^? _GitOptions)
)
(\(f, g) v -> f v & _GitOptions .~ g)
$ (,) <$> gitICodec .= view _1 <*> gitOptionsCodec .= view _2
--------------------------------------------------------------------------------
pypiCodec :: TomlCodec PackageFetcher
pypiCodec =
Toml.textBy
unsupportError
(Right . pypiFetcher)
"fetch.pypi"
--------------------------------------------------------------------------------
openVsxCodec :: TomlCodec PackageFetcher
openVsxCodec =
textBy
unsupportError
( \t -> case T.split (== '.') t of
-- assume we can't have '.' in extension's name
[publisher, extName] -> Right $ openVsxFetcher (publisher, extName)
_ -> Left "unexpected openvsx fetcher: it should be something like [publisher]/[extName]"
)
"fetch.openvsx"
--------------------------------------------------------------------------------
vscodeMarketplaceCodec :: TomlCodec PackageFetcher
vscodeMarketplaceCodec =
textBy
unsupportError
( \t -> case T.split (== '.') t of
-- assume we can't have '.' in extension's name
[publisher, extName] -> Right $ vscodeMarketplaceFetcher (publisher, extName)
_ -> Left "unexpected vscode marketplace fetcher: it should be something like [publisher]/[extName]"
)
"fetch.vsmarketplace"
--------------------------------------------------------------------------------
urlCodec :: TomlCodec PackageFetcher
urlCodec =
Toml.textBy
unsupportError
(\t -> Right $ \(coerce -> v) -> urlFetcher $ T.replace "$ver" v t)
"fetch.url"