module Cachix.Client.NixVersion
  ( assertNixVersion,
    parseNixVersion,
  )
where

import Data.Text as T
import Data.Versions
import Protolude
import System.Process (readProcessWithExitCode)

assertNixVersion :: IO (Either Text ())
assertNixVersion :: IO (Either Text ())
assertNixVersion = do
  (exitcode :: ExitCode
exitcode, out :: String
out, err :: String
err) <- String -> [String] -> String -> IO (ExitCode, String, String)
readProcessWithExitCode "nix-env" ["--version"] String
forall a. Monoid a => a
mempty
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String
err String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== "") (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
forall a (m :: * -> *). (Print a, MonadIO m) => a -> m ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ "nix-env stderr: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
err
  Either Text () -> IO (Either Text ())
forall (m :: * -> *) a. Monad m => a -> m a
return (Either Text () -> IO (Either Text ()))
-> Either Text () -> IO (Either Text ())
forall a b. (a -> b) -> a -> b
$ case ExitCode
exitcode of
    ExitFailure i :: Int
i -> Text -> Either Text ()
forall a b. a -> Either a b
Left (Text -> Either Text ()) -> Text -> Either Text ()
forall a b. (a -> b) -> a -> b
$ "'nix-env --version' exited with " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a b. (Show a, StringConv String b) => a -> b
show Int
i
    ExitSuccess -> Text -> Either Text ()
parseNixVersion (Text -> Either Text ()) -> Text -> Either Text ()
forall a b. (a -> b) -> a -> b
$ String -> Text
forall a b. StringConv a b => a -> b
toS String
out

parseNixVersion :: Text -> Either Text ()
parseNixVersion :: Text -> Either Text ()
parseNixVersion output :: Text
output =
  let verStr :: Text
verStr = Int -> Text -> Text
T.drop 14 (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text
T.strip Text
output
      err :: Text
err = "Couldn't parse 'nix-env --version' output: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
output
   in case Text -> Either ParsingError Versioning
versioning Text
verStr of
        Left _ -> Text -> Either Text ()
forall a b. a -> Either a b
Left Text
err
        Right ver :: Versioning
ver
          | Text
verStr Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== "" -> Text -> Either Text ()
forall a b. a -> Either a b
Left Text
err
          | Versioning
ver Versioning -> Versioning -> Bool
forall a. Ord a => a -> a -> Bool
< SemVer -> Versioning
Ideal (Word -> Word -> Word -> [VChunk] -> [VChunk] -> SemVer
SemVer 2 0 1 [] []) -> Text -> Either Text ()
forall a b. a -> Either a b
Left "Nix 2.0.2 or lower is not supported. Please upgrade: https://nixos.org/nix/"
          | Bool
otherwise -> () -> Either Text ()
forall a b. b -> Either a b
Right ()