Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revisiting Stack's approach to ghc-pkg unregister #6225

Closed
mpilgrem opened this issue Aug 29, 2023 · 1 comment
Closed

Revisiting Stack's approach to ghc-pkg unregister #6225

mpilgrem opened this issue Aug 29, 2023 · 1 comment

Comments

@mpilgrem
Copy link
Member

mpilgrem commented Aug 29, 2023

The context for revisiting Stack's current approach to ghc-pkg unregister is #5639. There are two aspects to that approach.

1. Stack.GhcPkg.unregisterGhcPkgIds

Stack.GhcPkg.unregisterGhcPkgIds has (using the flag --user):

unregisterGhcPkgIds pkgexe pkgDb epgids = do
  eres <- ghcPkg pkgexe [pkgDb] args
  case eres of
    Left e -> prettyWarn $ string $ displayException e
    Right _ -> pure ()
 where
  (idents, gids) = partitionEithers $ toList epgids
  args = "unregister" : "--user" : "--force" :
    map packageIdentifierString idents ++
    if null gids then [] else "--ipid" : map ghcPkgIdString gids

but Stack.GhcPkg.ghcPkg (not exported) has (using packageDbFlags pkgDbs):

ghcPkg pkgexe@(GhcPkgExe pkgPath) pkgDbs args = do
  eres <- go
  case eres of
    Left _ -> do
      mapM_ (createDatabase pkgexe) pkgDbs
      go
    Right _ -> pure eres
 where
  pkg = toFilePath pkgPath
  go = tryAny $ BL.toStrict . fst <$> proc pkg args' readProcess_
  args' = packageDbFlags pkgDbs ++ args

where (using the flag --no-user-package-db)

packageDbFlags pkgDbs =
    "--no-user-package-db"
  : map (\x -> "--package-db=" ++ toFilePath x) pkgDbs

The --no-user-package-db ghc-pkg flag makes the use of the --user ghc-pkg flag redundant, as GHC's utils\ghc-pkg\Main.getPkgDatabases has (from at least GHC 8.0.1) (extracts):

let no_user_db = FlagNoUserDb `elem` my_flags

  mb_user_conf <-
    case [ f | FlagUserConfig f <- my_flags ] of
      _ | no_user_db -> return Nothing

2. In Stack.Build.Execute.singleBuild, using GHC_PACKAGE_PATH

Stack.Build.Execute.singleBuild has (extracts):

        -- We want to ignore the global and user databases.
        -- Unfortunately, ghc-pkg doesn't take such arguments on the
        -- command line. Instead, we'll set GHC_PACKAGE_PATH. See:
        -- https://github.com/commercialhaskell/stack/issues/1146

        let modifyEnv = Map.insert
              (ghcPkgPathEnvVar wc)
              (T.pack $ toFilePathNoTrailingSep $ bcoSnapDB eeBaseConfigOpts)

        withModifyEnvVars modifyEnv $ do
          GhcPkgExe ghcPkgExe <- getGhcPkgExe

          -- first unregister everything that needs to be unregistered
          forM_ allToUnregister $ \packageName -> catchAny
            ( readProcessNull
                (toFilePath ghcPkgExe)
                [ "unregister", "--force", packageName]
            )
            (const (pure ()))

but the Haskell comment about the functionality of ghc-pkg is not true (from at least GHC 8.0.1) - ghc-pkg --no-user-package-db --package-db=<db> unregister <P> only operates on <db>, there is no need to use the environment variable.

Looking at the code in the GHC repository at tag ghc-8.0.1-release, in utils\ghc-pkg\Main.hs, for example (extracts):

modfiyPackage

modifyPackage fn pkgarg verbosity my_flags force = do
  (db_stack, Just _to_modify, flag_dbs) <-
      getPkgDatabases verbosity True{-modify-} True{-use user-}
                                True{-use cache-} False{-expand vars-} my_flags

  -- Do the search for the package respecting flags...
  (db, ps) <- fmap head $ findPackagesByDB flag_dbs pkgarg

getPkgDatabases

  let flag_db_names | null db_flags = env_stack
                    | otherwise     = reverse (nub db_flags) --<<< This is the relevant limb

  -- the database we actually modify is the one mentioned
  -- rightmost on the command-line.
  let to_modify
        | not modify    = Nothing
        | null db_flags = Just virt_global_conf
        | otherwise     = Just (last db_flags) --<<< This is the relevant limb
  db_stack  <- ...
  let flag_db_stack = [ db | db_name <- flag_db_names,
                        db <- db_stack, location db == db_name ]
  return (db_stack, to_modify, flag_db_stack)

Alternatively, looking at the code in the master branch of the GHC repository (extracts):

modifyPackage

(db_stack, GhcPkg.DbOpenReadWrite db, _flag_dbs) <-
    getPkgDatabases verbosity (GhcPkg.DbOpenReadWrite $ ContainsPkg pkgarg)
      True{-use user-} True{-use cache-} False{-expand vars-} my_flags

  let
      pkgs    = packages db

      -- Get package respecting flags...
      ps = findPackage pkgarg pkgs

getPkgDatabases

getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do
...
  let flag_db_names | null db_flags = env_stack
                    | otherwise     = reverse (nub db_flags) --<<< This is the relevant limb

  (db_stack, db_to_operate_on) <- getDatabases top_dir mb_user_conf
                                               flag_db_names final_stack top_db

 where
    getDatabases top_dir mb_user_conf flag_db_names
                 final_stack top_db = case mode of
    ...
      -- The package db we open in read write mode is the first one included in
      -- flag_db_names that contains specified package. Therefore we need to
      -- open each one in read/write mode first and decide whether it's for
      -- modification based on its contents.
      GhcPkg.DbOpenReadWrite (ContainsPkg pkgarg) -> do
mpilgrem added a commit that referenced this issue Aug 30, 2023
@mpilgrem
Copy link
Member Author

The comment about ghc-pkg functionality above:

-- We want to ignore the global and user databases.
-- Unfortunately, ghc-pkg doesn't take such arguments on the
-- command line. Instead, we'll set GHC_PACKAGE_PATH. See:
-- https://github.com/commercialhaskell/stack/issues/1146

was added by @snoyberg in 6b8fd22 on 12 Oct 2015, in response to #1146. At that time, the most recently released GHC was GHC 7.10.2 (on 29 July 2015). I do not know what versions of GHC/ghc-pkg Stack was seeking to support at that time.

mpilgrem added a commit that referenced this issue Sep 2, 2023
mpilgrem added a commit that referenced this issue Sep 3, 2023
mpilgrem added a commit that referenced this issue Sep 3, 2023
mpilgrem added a commit that referenced this issue Sep 3, 2023
mpilgrem added a commit that referenced this issue Sep 3, 2023
mpilgrem added a commit that referenced this issue Sep 3, 2023
mpilgrem added a commit that referenced this issue Sep 3, 2023
mpilgrem added a commit that referenced this issue Sep 8, 2023
mpilgrem added a commit that referenced this issue Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant