Skip to content

Re-design the ProgramDb abstraction to avoid accidentally dropping unconfigured programs #9840

Open
@sheaf

Description

@sheaf

We have

data ProgramDb = ProgramDb
  { unconfiguredProgs :: UnconfiguredProgs
  , progSearchPath :: ProgramSearchPath
  , configuredProgs :: ConfiguredProgs
  }

-- | Note that this instance does not preserve the known 'Program's.
-- See 'restoreProgramDb' for details.
instance Binary ProgramDb where
  put db = do
    put (progSearchPath db)
    put (configuredProgs db)

  get = do
    searchpath <- get
    progs <- get
    return $!
      emptyProgramDb
        { progSearchPath = searchpath
        , configuredProgs = progs
        }

Note here that the Binary instance for ProgramDb discards the unconfigured programs. This is because arbitrary functions can be stored in that field (e.g. programFindVersion :: Verbosity -> FilePath -> IO (Maybe Version)).

However, this easily leads to bugs; #2241 was an example. I ran into another bug today, which was that the configureCompiler function in cabal-install would also drop unconfigured programs, which could lead to e.g. failing to find the ar executable (The program 'ar' is required but it could not be found.).

One first step which could help avoiding bugs is to define a newtype around ProgramDb and attach the Binary instance to that newtype instead. The wrapping/unwrapping of the newtype would hopefully introduce the appropriate amount of ceremony to avoid accidents.

More ambitiously, we could re-design ProgramDb, e.g. by introducing a serialisable DSL for unconfigured programs, or perhaps by using static pointers.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions