content: {-# OPTIONS_GHC -Wall #-}
  {-# LANGUAGE BangPatterns #-}
  
  module Stuff
    ( details
    , interfaces
    , objects
    , prepublishDir
    , elmi
    , elmo
    , temp
    , findRoot
    , findRootHelp
    , withRootLock
    , withRegistryLock
    , PackageCache
    , getPackageCache
    , registry
    , package
    , getReplCache
    , getElmHome
    )
    where
  
  
  import qualified System.Directory as Dir
  import qualified System.Environment as Env
  import qualified System.FileLock as Lock
  import qualified System.FilePath as FP
  import System.FilePath ((</>), (<.>))
  
  import qualified Elm.ModuleName as ModuleName
  import qualified Elm.Package as Pkg
  import qualified Elm.Version as V
  
  
  import Lamdera ((&))
  import qualified Lamdera
  
  -- PATHS
  
  
  stuff :: FilePath -> FilePath
  stuff root =
    root </> "elm-stuff" </> compilerVersion
  
  
  details :: FilePath -> FilePath
  details root =
    stuff root </> "d.dat"
  
  
  interfaces :: FilePath -> FilePath
  interfaces root =
    stuff root </> "i.dat"
  
  
  objects :: FilePath -> FilePath
  objects root =
    stuff root </> "o.dat"
  
  
  prepublishDir :: FilePath -> FilePath
  prepublishDir root =
    stuff root </> "prepublish"
  
  
  compilerVersion :: FilePath
  compilerVersion =
    V.toChars V.compiler
  
  
  
  -- ELMI and ELMO
  
  
  elmi :: FilePath -> ModuleName.Raw -> FilePath
  elmi root name =
    toArtifactPath root name "elmi"
  
  
  elmo :: FilePath -> ModuleName.Raw -> FilePath
  elmo root name =
    toArtifactPath root name "elmo"
  
  
  toArtifactPath :: FilePath -> ModuleName.Raw -> String -> FilePath
  toArtifactPath root name ext =
    stuff root </> ModuleName.toHyphenPath name <.> ext
  
  
  
  -- TEMP
  
  
  temp :: FilePath -> String -> FilePath
  temp root ext =
    stuff root </> "temp" <.> ext
  
  
  
  -- ROOT
  
  
  findRoot :: IO (Maybe FilePath)
  findRoot =
    do  dir <- Dir.getCurrentDirectory
        findRootHelp (FP.splitDirectories dir)
  
  
  findRootHelp :: [String] -> IO (Maybe FilePath)
  findRootHelp dirs =
    case dirs of
      [] ->
        return Nothing
  
      _:_ ->
        do  exists <- Dir.doesFileExist (FP.joinPath dirs </> "elm.json")
            if exists
              then return (Just (FP.joinPath dirs))
              else findRootHelp (init dirs)
  
  
  
  -- LOCKS
  
  
  withRootLock :: FilePath -> IO a -> IO a
  withRootLock root work =
    do  let dir = stuff root
        Dir.createDirectoryIfMissing True dir
        Lock.withFileLock (dir </> "lock") Lock.Exclusive (\_ -> work)
          & Lamdera.alternativeImplementation (do
              Lamdera.debug "🔒 withRootLock"
              !res <- Lock.withFileLock (dir </> "lock") Lock.Exclusive (\_ -> work)
              Lamdera.debug "🔓 unlocking withRootLock"
              pure res
            )
  
  
  withRegistryLock :: PackageCache -> IO a -> IO a
  withRegistryLock (PackageCache dir) work =
    Lock.withFileLock (dir </> "lock") Lock.Exclusive (\_ -> work)
  
  
  
  -- PACKAGE CACHES
  
  
  newtype PackageCache = PackageCache FilePath
  
  
  getPackageCache :: IO PackageCache
  getPackageCache =
    PackageCache <$> getCacheDir "packages"
  
  
  registry :: PackageCache -> FilePath
  registry (PackageCache dir) =
    dir </> "registry.dat"
  
  
  package :: PackageCache -> Pkg.Name -> V.Version -> FilePath
  package (PackageCache dir) name version =
    dir </> Pkg.toFilePath name </> V.toChars version
  
  
  
  -- CACHE
  
  
  getReplCache :: IO FilePath
  getReplCache =
    getCacheDir "repl"
  
  
  getCacheDir :: FilePath -> IO FilePath
  getCacheDir projectName =
    do  home <- getElmHome
        let root = home </> compilerVersion </> projectName
        Dir.createDirectoryIfMissing True root
        return root
  
  
  getElmHome :: IO FilePath
  getElmHome =
    do  maybeCustomHome <- Env.lookupEnv "ELM_HOME"
        case maybeCustomHome of
          Just customHome -> return customHome
          Nothing -> Dir.getAppUserDataDirectory "elm"
            -- & Lamdera.alternativeImplementation (Dir.getAppUserDataDirectory "lamdera")
  