packages feed

hie-bios 0.7.1 → 0.7.2

raw patch · 10 files changed

+108/−62 lines, 10 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- HIE.Bios.Cradle: readProcessWithOutputFile :: LoggingFunction -> FilePath -> CreateProcess -> IO (ExitCode, [String], [String], [String])
+ HIE.Bios.Cradle: readProcessWithOutputs :: Outputs -> LoggingFunction -> FilePath -> CreateProcess -> IO (ExitCode, [String], [String], [(OutputName, Maybe [String])])

Files

ChangeLog.md view
@@ -1,5 +1,11 @@ # ChangeLog hie-bios +## 2020-12-16 - 0.7.2++* Faster Bios protocol [#271](https://github.com/mpickering/hie-bios/pull/271)+* Modify unreachable cabal website links [#259](https://github.com/mpickering/hie-bios/pull/259)+* Only take the last line of output in getRuntimeGhcX [#256](https://github.com/mpickering/hie-bios/pull/256)+ ## 2020-09-01 - 0.7.1  * Add explicit type for stack.yaml location [#243](https://github.com/mpickering/hie-bios/pull/243)
README.md view
@@ -209,7 +209,7 @@ This configuration should work in (almost) every standard project setup, since `cabal` finds the component associated to a given source file. However, due to an unfortunate [bug](https://github.com/haskell/cabal/issues/6622), this fails on some files with `cabal` versions older than `3.4`. So, to make your project loadable by older `cabal` versions, you can specify a component to load.-A [component](https://cabal.readthedocs.io/en/stable/nix-local-build.html?highlight=component#cabal-v2-build) is roughly speaking a library, executable, test-suite or benchmark in `cabal`.+A [component](https://cabal.readthedocs.io/en/latest/nix-local-build.html?highlight=component#cabal-v2-build) is roughly speaking a library, executable, test-suite or benchmark in `cabal`. The `hie.yaml` file looks like this:  ```yaml@@ -228,7 +228,7 @@     component: "lib:hie-bios" ``` -The component syntax `"lib:hie-bios"` refers to the library of the package `hie-bios`. For a complete reference of the component syntax, we refer to the [documentation](https://cabal.readthedocs.io/en/stable/nix-local-build.html?highlight=component#cabal-v2-build).+The component syntax `"lib:hie-bios"` refers to the library of the package `hie-bios`. For a complete reference of the component syntax, we refer to the [documentation](https://cabal.readthedocs.io/en/latest/nix-local-build.html?highlight=component#cabal-v2-build).  Note that `cabal` and `stack` have different ways of specifying their components.@@ -560,29 +560,23 @@   - default.nix ``` -For the `Bios` cradle type, there is an optional field for specifying a program-or shell command to obtain cradle dependencies from:+For the `Bios` cradle type, the newline-separated cradle dependencies must be written out+to the file specified by the `HIE_BIOS_DEPS` environment variable. +Previous versions implemented a different mechanism for collecting cradle dependencies+by means of a second program/shell field. This is still supported for backwards+compatibility:+ ```yaml cradle:   bios:-    program: ./flags.sh     dependency-program: ./dependency.sh ``` ```yaml cradle:   bios:-    shell: build-tool flags $HIE_BIOS_ARG > $HIE_BIOS_OUTPUT     dependency-shell: build-tool dependencies $HIE_BIOS_ARG > $HIE_BIOS_OUTPUT ```--The dependency program or command is executed in a similar fashion to the bios-program, using the environment variables HIE_BIOS_ARG and HIE_BIOS_OUTPUT to-communicate respectively the path of the source file being loaded, and the path-where the set of dependency paths should be written, one per line,-and relative to the root of the cradle, not to the location of the program.--Programs and shell commands for flags and dependencies can be mixed and matched.  ## Configuration specification 
hie-bios.cabal view
@@ -1,6 +1,6 @@ Cabal-Version:          2.2 Name:                   hie-bios-Version:                0.7.1+Version:                0.7.2 Author:                 Matthew Pickering <matthewtpickering@gmail.com> Maintainer:             Matthew Pickering <matthewtpickering@gmail.com> License:                BSD-3-Clause@@ -19,6 +19,10 @@                         tests/configs/*.yaml                         tests/projects/symlink-test/a/A.hs                         tests/projects/symlink-test/hie.yaml+                        tests/projects/deps-bios-new/A.hs+                        tests/projects/deps-bios-new/B.hs+                        tests/projects/deps-bios-new/hie-bios.sh+                        tests/projects/deps-bios-new/hie.yaml                         tests/projects/multi-direct/A.hs                         tests/projects/multi-direct/B.hs                         tests/projects/multi-direct/hie.yaml@@ -142,8 +146,8 @@   autogen-modules:      Paths_hie_bios   Build-Depends:                         base                 >= 4.8 && < 5,-                        aeson                >= 1.4.1 && < 2,-                        base16-bytestring    >= 0.1.1 && < 0.2,+                        aeson                >= 1.4.5 && < 2,+                        base16-bytestring    >= 0.1.1 && < 1.1,                         bytestring           >= 0.10.8 && < 0.11,                         deepseq              >= 1.4.3 && < 1.5,                         containers           >= 0.5.10 && < 0.7,@@ -160,7 +164,7 @@                         unix-compat          >= 0.5.1 && < 0.6,                         unordered-containers >= 0.2.9 && < 0.3,                         vector               >= 0.12.0 && < 0.13,-                        yaml                 >= 0.8.32 && < 0.12,+                        yaml                 >= 0.10.0 && < 0.12,                         hslogger             >= 1.2 && < 1.4,                         file-embed           >= 0.0.11 && < 1,                         conduit              >= 1.3 && < 2,
src/HIE/Bios/Cradle.hs view
@@ -18,7 +18,7 @@     , isDefaultCradle     , isOtherCradle     , getCradle-    , readProcessWithOutputFile+    , readProcessWithOutputs     , readProcessWithCwd     , makeCradleResult   ) where@@ -33,6 +33,7 @@ import HIE.Bios.Config import HIE.Bios.Environment (getCacheDir) import System.Directory hiding (findFile)+import Control.Monad.Trans.Cont import Control.Monad.Trans.Maybe import System.FilePath import Control.Monad@@ -59,6 +60,8 @@ import           Data.Maybe (fromMaybe, maybeToList) import           GHC.Fingerprint (fingerprintString) +hie_bios_output :: String+hie_bios_output = "HIE_BIOS_OUTPUT" ----------------------------------------------------------------  -- | Given root\/foo\/bar.hs, return root\/hie.yaml, or wherever the yaml file was found.@@ -357,10 +360,10 @@ biosDepsAction :: LoggingFunction -> FilePath -> Maybe Callable -> FilePath -> IO [FilePath] biosDepsAction l wdir (Just biosDepsCall) fp = do   biosDeps' <- callableToProcess biosDepsCall (Just fp)-  (ex, sout, serr, args) <- readProcessWithOutputFile l wdir biosDeps'+  (ex, sout, serr, [(_, args)]) <- readProcessWithOutputs [hie_bios_output] l wdir biosDeps'   case ex of     ExitFailure _ ->  error $ show (ex, sout, serr)-    ExitSuccess -> return args+    ExitSuccess -> return $ fromMaybe [] args biosDepsAction _ _ Nothing _ = return []  biosAction :: FilePath@@ -371,13 +374,17 @@            -> IO (CradleLoadResult ComponentOptions) biosAction wdir bios bios_deps l fp = do   bios' <- callableToProcess bios (Just fp)-  (ex, _stdo, std, res) <- readProcessWithOutputFile l wdir bios'-  deps <- biosDepsAction l wdir bios_deps fp+  (ex, _stdo, std, [(_, res),(_, mb_deps)]) <-+    readProcessWithOutputs [hie_bios_output, "HIE_BIOS_DEPS"] l wdir bios'++  deps <- case mb_deps of+    Just x  -> return x+    Nothing -> biosDepsAction l wdir bios_deps fp         -- Output from the program should be written to the output file and         -- delimited by newlines.         -- Execute the bios action and add dependencies of the cradle.         -- Removes all duplicates.-  return $ makeCradleResult (ex, std, wdir, res) deps+  return $ makeCradleResult (ex, std, wdir, fromMaybe [] res) deps  callableToProcess :: Callable -> Maybe String -> IO CreateProcess callableToProcess (Command shellCommand) file = do@@ -491,8 +498,9 @@ cabalAction work_dir mc l fp = do   withCabalWrapperTool ("ghc", []) work_dir $ \wrapper_fp -> do     let cab_args = ["v2-repl", "--with-compiler", wrapper_fp, fromMaybe (fixTargetPath fp) mc]-    (ex, output, stde, args) <--      readProcessWithOutputFile l work_dir (proc "cabal" cab_args)+    (ex, output, stde, [(_,mb_args)]) <-+      readProcessWithOutputs [hie_bios_output] l work_dir (proc "cabal" cab_args)+    let args = fromMaybe [] mb_args     case processCabalWrapperArgs args of         Nothing -> do           -- Best effort. Assume the working directory is the@@ -502,7 +510,7 @@                     ["Failed to parse result of calling cabal"                      , unlines output                      , unlines stde-                     , unlines args])+                     , unlines $ args])         Just (componentDir, final_args) -> do           deps <- cabalCradleDependencies work_dir componentDir           pure $ makeCradleResult (ex, stde, componentDir, final_args) deps@@ -615,16 +623,17 @@   let ghcProcArgs = ("stack", stackYamlProcessArgs syaml <> ["exec", "ghc", "--"])   -- Same wrapper works as with cabal   withCabalWrapperTool ghcProcArgs work_dir $ \wrapper_fp -> do-    (ex1, _stdo, stde, args) <--      readProcessWithOutputFile l work_dir $+    (ex1, _stdo, stde, [(_, mb_args)]) <-+      readProcessWithOutputs [hie_bios_output] l work_dir $         stackProcess syaml                       $  ["repl", "--no-nix-pure", "--with-ghc", wrapper_fp]                       <> [ comp | Just comp <- [mc] ]     (ex2, pkg_args, stdr, _) <--      readProcessWithOutputFile l work_dir $+      readProcessWithOutputs [hie_bios_output] l work_dir $         stackProcess syaml ["path", "--ghc-package-path"]     let split_pkgs = concatMap splitSearchPath pkg_args         pkg_ghc_args = concatMap (\p -> ["-package-db", p] ) split_pkgs+        args = fromMaybe [] mb_args     case processCabalWrapperArgs args of         Nothing -> do           -- Best effort. Assume the working directory is the@@ -776,49 +785,65 @@   e <- getEnvironment   return $ Map.toList $ Map.delete "GHC_PACKAGE_PATH" $ Map.fromList e --- | Call a given process.--- * A special file is created for the process to write to, the process can discover the name of--- the file by reading the @HIE_BIOS_OUTPUT@ environment variable. The contents of this file is--- returned by the function.+type Outputs = [OutputName]+type OutputName = String++-- | Call a given process with temp files for the process to write to.+-- * The process can discover the temp files paths by reading the environment.+-- * The contents of the temp files are returned by this function, if any. -- * The logging function is called every time the process emits anything to stdout or stderr. -- it can be used to report progress of the process to a user. -- * The process is executed in the given directory.-readProcessWithOutputFile-  :: LoggingFunction -- ^ Output of the process is streamed into this function.+readProcessWithOutputs+  :: Outputs  -- ^ Names of the outputs produced by this process+  -> LoggingFunction -- ^ Output of the process is streamed into this function.   -> FilePath -- ^ Working directory. Process is executed in this directory.   -> CreateProcess -- ^ Parameters for the process to be executed.-  -> IO (ExitCode, [String], [String], [String])-readProcessWithOutputFile l work_dir cp = do-  old_env <- getCleanEnvironment+  -> IO (ExitCode, [String], [String], [(OutputName, Maybe [String])])+readProcessWithOutputs outputNames l work_dir cp = flip runContT return $ do+  old_env <- liftIO getCleanEnvironment+  output_files <- traverse (withOutput old_env) outputNames -  withHieBiosOutput old_env $ \output_file -> do-    -- Pipe stdout directly into the logger-    let process = cp { env = Just-                              $ (hieBiosOutput, output_file)-                              : (fromMaybe old_env (env cp)),-                       cwd = Just work_dir-                      }+  let process = cp { env = Just $ output_files ++ fromMaybe old_env (env cp),+                     cwd = Just work_dir+                    }      -- Windows line endings are not converted so you have to filter out `'r` characters-    let  loggingConduit = (C.decodeUtf8  C..| C.lines C..| C.filterE (/= '\r')  C..| C.map T.unpack C..| C.iterM l C..| C.sinkList)-    (ex, stdo, stde) <- sourceProcessWithStreams process mempty loggingConduit loggingConduit-    res <- withFile output_file ReadMode $ \handle -> do-             hSetBuffering handle LineBuffering-             !res <- force <$> hGetContents handle-             return res+  let  loggingConduit = C.decodeUtf8  C..| C.lines C..| C.filterE (/= '\r')  C..| C.map T.unpack C..| C.iterM l C..| C.sinkList+  (ex, stdo, stde) <- liftIO $ sourceProcessWithStreams process mempty loggingConduit loggingConduit -    return (ex, stdo, stde, lines (filter (/= '\r') res))+  res <- forM output_files $ \(name,path) ->+          liftIO $ (name,) <$> readOutput path +  return (ex, stdo, stde, res)+     where-      withHieBiosOutput :: [(String,String)] -> (FilePath -> IO a) -> IO a-      withHieBiosOutput env' action = do-        let mbHieBiosOut = lookup hieBiosOutput env'-        case mbHieBiosOut of-          Just file@(_:_) -> action file-          _ -> withSystemTempFile "hie-bios" $-                 \ file h -> hClose h >> action file+      readOutput :: FilePath -> IO (Maybe [String])+      readOutput path = do+        haveFile <- doesFileExist path+        if haveFile+          then withFile path ReadMode $ \handle -> do+            hSetBuffering handle LineBuffering+            !res <- force <$> hGetContents handle+            return $ Just $ lines $ filter (/= '\r') res+          else+            return Nothing -      hieBiosOutput = "HIE_BIOS_OUTPUT"+      withOutput :: [(String,String)] -> OutputName -> ContT a IO (OutputName, String)+      withOutput env' name =+        case lookup name env' of+          Just file@(_:_) -> ContT $ \action -> do+            removeFileIfExists file+            action (name, file)+          _ -> ContT $ \action -> withSystemTempFile name $ \ file h -> do+            hClose h+            removeFileIfExists file+            action (name, file)++removeFileIfExists :: FilePath -> IO ()+removeFileIfExists f = do+  yes <- doesFileExist f+  when yes (removeFile f)  makeCradleResult :: (ExitCode, [String], FilePath, [String]) -> [FilePath] -> CradleLoadResult ComponentOptions makeCradleResult (ex, err, componentDir, gopts) deps =
src/HIE/Bios/Environment.hs view
@@ -309,5 +309,9 @@ anyToken = satisfy $ const True  -- Used for clipping the trailing newlines on GHC output+-- Also only take the last line of output+-- (Stack's ghc output has a lot of preceding noise from 7zip etc) trim :: String -> String-trim = dropWhileEnd isSpace+trim s = case lines s of+  [] -> s+  ls -> dropWhileEnd isSpace $ last ls
tests/BiosTests.hs view
@@ -183,6 +183,7 @@   = [ testCaseSteps "simple-bios" $ testDirectory isBiosCradle "./tests/projects/simple-bios" "B.hs"     , testCaseSteps "simple-bios-ghc" $ testDirectory isBiosCradle "./tests/projects/simple-bios-ghc" "B.hs"     , testCaseSteps "simple-bios-deps" $ testLoadCradleDependencies isBiosCradle "./tests/projects/simple-bios" "B.hs" (assertEqual "dependencies" ["hie-bios.sh", "hie.yaml"])+    , testCaseSteps "simple-bios-deps-new" $ testLoadCradleDependencies isBiosCradle "./tests/projects/deps-bios-new" "B.hs" (assertEqual "dependencies" ["hie-bios.sh", "hie.yaml"])     ]   | otherwise   = []
+ tests/projects/deps-bios-new/A.hs view
@@ -0,0 +1,1 @@+module A where
+ tests/projects/deps-bios-new/B.hs view
@@ -0,0 +1,3 @@+module B where++import A
+ tests/projects/deps-bios-new/hie-bios.sh view
@@ -0,0 +1,5 @@+echo "-Wall" >> $HIE_BIOS_OUTPUT+echo "A" >> $HIE_BIOS_OUTPUT+echo "B" >> $HIE_BIOS_OUTPUT+echo "hie-bios.sh" >> $HIE_BIOS_DEPS+echo "hie.yaml" >> $HIE_BIOS_DEPS
+ tests/projects/deps-bios-new/hie.yaml view
@@ -0,0 +1,3 @@+cradle:+  bios:+    program: ./hie-bios.sh