cabal2nix icon indicating copy to clipboard operation
cabal2nix copied to clipboard

Improve error message when given `NoHackageTarballFound`

Open stianlagstad opened this issue 2 years ago • 8 comments

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.)

stianlagstad avatar Nov 17 '21 20:11 stianlagstad

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.

expipiplus1 avatar Dec 01 '21 08:12 expipiplus1

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?

stianlagstad avatar Dec 01 '21 09:12 stianlagstad

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.

expipiplus1 avatar Dec 01 '21 09:12 expipiplus1

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 within hackage-db here, in the hackageTarball function.
  • The hackageTarball function is used within cabal2nix here, in the loadHackageDB function. Would that be the appropriate place to catch the exception?
  • If not, then I see that the loadHackageDB function is used here, in the getPackage function. Could that be a good place to catch the exception?
  • If not, then I see that the getPackage function is used here, in the cabal2nix' function, which is again used in the cabal2nix function, which is again is what's called from main.

stianlagstad avatar Dec 01 '21 09:12 stianlagstad

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.

expipiplus1 avatar Dec 01 '21 16:12 expipiplus1

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 avatar Dec 01 '21 19:12 stianlagstad

@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?

maralorn avatar Dec 03 '21 00:12 maralorn

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."

stianlagstad avatar Dec 03 '21 14:12 stianlagstad