cabal2nix
cabal2nix copied to clipboard
Improve error message when given `NoHackageTarballFound`
I ran into this issue today, and found this: https://github.com/NixOS/cabal2nix/issues/423. The solution, as stated in that thread, was to run cabal update
. Could that be a hint that's given along with the NoHackageTarballFound
error? To save others from googling in the future.
(I wasn't sure whether to create this issue here or in https://github.com/NixOS/hackage-db.)
Probably best to implement displayException
for NoHackageTarBallFound
to include this information and set the exception handler in cabal2nix to use that when reporting exceptions at the top level.
Thank you very much for responding! Could you give me some pointers so that I may try to fix this? I'm new to haskell, but I assume displayException
is this. Would you want that implemented here? Or could a new instance be written within cabal2nix?
displayException
would have to be implemented in hackage-db, and then maybe something like https://hackage.haskell.org/package/uncaught-exception-0.1.0/docs/Control-Exception-Uncaught.html#v:setDisplayExceptionHandler used in cabal2nix.
A less invasive fix might be to just catch NoHackageTarBallFound
in cabal2nix
and print out some information there and rethrow.
Thanks again. I'd like to try to create a pull request with the less invasive fix (it'll be helpful for me even though the PR is rejected in the end for the more invasive approach). Where should the exception be caught, in your opinion?
Trying to follow the exception:
- I see that
NoHackageTarballFound
is thrown from withinhackage-db
here, in thehackageTarball
function. - The
hackageTarball
function is used withincabal2nix
here, in theloadHackageDB
function. Would that be the appropriate place to catch the exception? - If not, then I see that the
loadHackageDB
function is used here, in thegetPackage
function. Could that be a good place to catch the exception? - If not, then I see that the
getPackage
function is used here, in thecabal2nix'
function, which is again used in thecabal2nix
function, which is again is what's called frommain
.
I'd be tempted to put it at the highest level, that way it's most resilient to future code reorganizations. If, going forward, there's any other useful information to attach to exceptions then it can all take place in one top-level function.
I'm working on giving it a shot, but am stuck at the moment. Will try more later. What I've got:
import Control.Exception ( try, Exception )
cabal2nix :: [String] -> IO ()
cabal2nix input = do
-- This I understand:
let fun = parseArgs >=> cabal2nix' >=> putStrLn . either render prettyShow :: [String] -> IO ()
-- But I can't seem to figure out the type of this one:
tryFun <- try (fun input) :: Exception e => Either e () -- this type annotation is wrong
Edit:
It seems to me that I can't use Exception e => Either e (SomeThingElse)
. That I need to use a specific type instead of exception there. Like Either NoHackageTarballFound SomeThingElse
. But I'm struggling to get a hold of NoHackageTarballFound
. I see that it's not exported from https://github.com/NixOS/hackage-db/blob/master/src/Distribution/Hackage/DB/Errors.hs - can I then refer to it from cabal2nix?
Edit2:
I think that this would work:
cabal2nix :: [String] -> IO ()
cabal2nix input = do
let fun = parseArgs >=> cabal2nix' >=> putStrLn . either render prettyShow :: [String] -> IO ()
tryFun <- try (fun input) :: IO (Either SomeException ())
case tryFun of
Left err ->
case err of
NoHackageTarballFound -> pure ()
_ -> pure ()
Right succ ->
succ
but I'm having problems importing NoHackageTarballFound
. Am I right in that I can't use that here, as it's not exported from this module?
Edit3: I'm stuck at the problem that I'm not able to import the module that has the exception type.
@stianlagstad That package has no explicit export list so everything in it should be exported. Also it’s listed as an exported module. Have you inserted an import Distribution.Hackage.DB.Errors
in your file? What error do you meet?
Thanks @maralorn ! I was indeed having problems importing it.
I think that this is something that would work:
cabal2nix :: [String] -> IO ()
cabal2nix input = do
let fun = parseArgs >=> cabal2nix' >=> putStrLn . either render prettyShow
fun input `catch` h where
h NoHackageTarballFound = do
putStrLn "Could not find that package with that version. Running `cabal update` and then retrying might help."