Compare commits
1 commit
d82d4dbce0
...
af06fbace0
Author | SHA1 | Date | |
---|---|---|---|
Félix Baylac-Jacqué | af06fbace0 |
98
ReproTest.hs
Executable file
98
ReproTest.hs
Executable file
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i runhaskell -p "haskellPackages.ghcWithPackages(p: with p; [ relude optparse-applicative process ])" -p nix -p diffoscope
|
||||
{-# LANGUAGE NoImplicitPrelude #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
import Relude
|
||||
|
||||
import Data.Maybe
|
||||
import GHC.IO.Handle
|
||||
import Control.Monad.Except
|
||||
import Control.DeepSeq
|
||||
import Options.Applicative
|
||||
import Data.Text hiding (foldl')
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.IO as T
|
||||
import qualified System.Exit as E
|
||||
import System.Process
|
||||
|
||||
|
||||
data Config = Config
|
||||
{ pkgName :: Text,
|
||||
ghcPath :: Text }
|
||||
|
||||
type ReproPaths = [Text]
|
||||
type StorePath = Text
|
||||
type NixError = Text
|
||||
type ReproStatus = Maybe ReproPaths
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
c <- execParser opts
|
||||
rs <- runExceptT $ repro c
|
||||
case rs of
|
||||
Left err -> T.putStr err >> exitFailure
|
||||
Right Nothing -> T.putStr "SUCCESS" >> exitSuccess
|
||||
Right (Just rp) -> T.putStr $ "Cannot Reproduce build:\n" <> unwords rp
|
||||
where
|
||||
opts = info (configParser <**> helper)
|
||||
( fullDesc
|
||||
<> header "ReproTest.hs - Test the GHC binary reproducibility for a hackage package"
|
||||
)
|
||||
|
||||
configParser :: Parser Config
|
||||
configParser = Config
|
||||
<$> strOption (long "package-name" <> short 'p' <> help "Hackage package to test")
|
||||
<*> strOption (long "ghc-nixexpr-path" <> short 'e' <> help "Path to the nix derivation retrieving the custom GHC checkpout you want to use.")
|
||||
|
||||
repro :: (MonadIO m) => Config -> ExceptT NixError m ReproStatus
|
||||
repro c = do
|
||||
-- 1. Nix instantiate derivation
|
||||
(eci, drvPath) <- streamRunCmd "nix-instantiate"
|
||||
[
|
||||
"--arg", "hs-pkg-name", "\"" <> pkgName c <> "\"",
|
||||
"--arg", "ghcSrcDrv", ghcPath c,
|
||||
"./repro.nix"
|
||||
] True
|
||||
-- 2. nix-store --realize /nix/store/xxx.drv
|
||||
(_, p1) <- streamRunCmd "nix-store"
|
||||
["--realise", "--quiet", drvPath] True
|
||||
-- 3. nix-store --realize --check /nix/store/xxx.drv
|
||||
(ecr2, p2) <- streamRunCmd "nix-store"
|
||||
["--realise", "--quiet", "-K", "--check", drvPath] False
|
||||
-- 4. If exit code > 1 => Just two repro paths
|
||||
if ecr2 == E.ExitSuccess
|
||||
then pure Nothing
|
||||
else pure $ Just [ p1, p2 ]
|
||||
|
||||
|
||||
|
||||
runDiffoscope :: ReproPaths -> IO StorePath
|
||||
runDiffoscope = undefined
|
||||
-- Take the two different paths.
|
||||
-- Run diffoscope on them.
|
||||
|
||||
-- Partially vendored from Shask
|
||||
-- TODO:
|
||||
-- - Handle custom Exp stacks in Shask.
|
||||
-- - Determine whether the out parsing should be part of the Shask API or not.
|
||||
-- - Release Shask.
|
||||
streamRunCmd :: (MonadIO m) => Text -> [Text] -> Bool -> ExceptT NixError m (E.ExitCode, StorePath)
|
||||
streamRunCmd cmd args fail = do
|
||||
liftIO . T.putStr $ "[+] " <> cmd <> " " <> unwords args <> "\n\n"
|
||||
(ec, out) <- liftIO $ withCreateProcess p progressFn
|
||||
when (ec /= E.ExitSuccess && fail) . throwError $ "Failed to run " <> cmd <> " " <> unwords args
|
||||
liftIO $ T.putStr $ " " <> "DONE\n\n"
|
||||
return (force ec, force . T.filter (/= '\n') $ out)
|
||||
where
|
||||
p = (proc (unpack cmd) (unpack <$> args)) { std_out = CreatePipe, std_err = CreatePipe }
|
||||
progressFn _ (Just hout) (Just herr) ph = go
|
||||
where
|
||||
go = do
|
||||
eof <- hIsEOF herr
|
||||
unless eof $ T.hGetLine herr >>= T.putStrLn
|
||||
mec <- getProcessExitCode ph
|
||||
case mec of
|
||||
(Just ec) -> T.hGetContents hout >>= \out -> pure (ec, out)
|
||||
Nothing -> go
|
||||
progressFn _ _ _ ph = error "Cannot open subprocess IO handles"
|
11
default.nix
11
default.nix
|
@ -2,12 +2,5 @@
|
|||
hs-pkg-name ? "wcwidth",
|
||||
ghcSrc ? /home/ninjatrappeur/Code/perso/haskell/ghc
|
||||
}:
|
||||
let
|
||||
ghcOverlay =
|
||||
import ./overlays/ghc.nix {
|
||||
inherit ghcSrc pkgs;
|
||||
};
|
||||
nixpkgsConfig = { overlays = [ ghcOverlay ]; };
|
||||
nixpkgsSrc = (import ./nix/sources.nix).nixpkgs;
|
||||
pkgs = import nixpkgsSrc nixpkgsConfig;
|
||||
in pkgs.customGhcHEAD."${hs-pkg-name}"
|
||||
|
||||
import ./repro.nix { inherit hs-pkg-name ghcSrc; }
|
||||
|
|
Loading…
Reference in a new issue