diff options
author | Daniel Gröber <dxld@darkboxed.org> | 2019-07-31 14:22:08 +0200 |
---|---|---|
committer | Daniel Gröber (dxld) <dxld@darkboxed.org> | 2019-09-17 17:48:26 +0200 |
commit | 65bd5532775f13d911f4def1059b614acca5a330 (patch) | |
tree | 4fc49551772a002508e7ab930ec3cc17b7d846ca /lib/Distribution/Helper | |
parent | 82777ce96e1ddad02033adc2f0c0c6f548e850ac (diff) |
Flesh out project discovery API
Diffstat (limited to 'lib/Distribution/Helper')
-rw-r--r-- | lib/Distribution/Helper/Discover.hs | 70 |
1 files changed, 48 insertions, 22 deletions
diff --git a/lib/Distribution/Helper/Discover.hs b/lib/Distribution/Helper/Discover.hs index b074261..9e6a7ca 100644 --- a/lib/Distribution/Helper/Discover.hs +++ b/lib/Distribution/Helper/Discover.hs @@ -14,7 +14,7 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <http://www.gnu.org/licenses/>. -{-# LANGUAGE GADTs #-} +{-# LANGUAGE GADTs, TypeFamilies, DataKinds #-} {-| Module : Distribution.Helper.Discover @@ -28,23 +28,30 @@ Portability : portable module Distribution.Helper.Discover ( findProjects - , findDistDirs - , findDistDirsWithHints + , getDefaultDistDir + , isValidDistDir ) where import Control.Monad.Writer -import Data.List import System.Directory import System.FilePath import CabalHelper.Compiletime.Types import CabalHelper.Compiletime.Cabal -import CabalHelper.Compiletime.Compat.Directory +-- | @findProjects dir@. Find available project instances in @dir@. +-- +-- For example, if the given directory contains both a @cabal.project@ and +-- a @stack.yaml@ file: +-- +-- >>> findProjects "." +-- [ Ex (ProjLocStackYaml "./stack.yaml"), Ex (ProjLocCabalV2File "./cabal.project") ] +-- +-- Note that this function only looks for "default" project markers. If you +-- want to for example support the common pattern of having multiple +-- @stack-<GHC_VER>.yaml@ files simply fill out a 'ProjLoc' yourself. In +-- this case 'ProjLocStackYaml'. findProjects :: FilePath -> IO [Ex ProjLoc] -findDistDirs :: ProjLoc pt -> [DistDir pt] -findDistDirsWithHints :: ProjLoc pt -> [FilePath] -> [DistDir pt] - findProjects dir = execWriterT $ do let cabalProject = dir </> "cabal.project" whenM (liftIO $ doesFileExist cabalProject) $ @@ -53,23 +60,42 @@ findProjects dir = execWriterT $ do whenM (liftIO $ doesFileExist stackYaml) $ tell [Ex $ ProjLocStackYaml stackYaml] join $ traverse (tell . pure . Ex . ProjLocV1Dir . takeDirectory) <$> - liftIO (findCabalFiles dir) + liftIO (findCabalFile dir) -findDistDirs (ProjLocV1CabalFile cabal _) = - [DistDirCabal SCV1 $ replaceFileName cabal "dist/"] -findDistDirs (ProjLocV1Dir dir) = [DistDirCabal SCV1 $ dir </> "dist/"] -findDistDirs (ProjLocV2File cabal) = - [DistDirCabal SCV2 $ replaceFileName cabal "dist-newstyle/"] -findDistDirs (ProjLocV2Dir dir) = [DistDirCabal SCV2 $ dir </> "dist-newstyle/"] -findDistDirs (ProjLocStackYaml _) = [DistDirStack Nothing] -findDistDirsWithHints = undefined +-- | @getDefaultDistDir pl@. Get the default dist-dir for the given project. +-- +-- Note that the path in the returned dist-dir might not exist yet if the +-- build-tool has never been run for this project before. This is fine as +-- far as @cabal-helper@ is concerned. It will simply invoke the build-tool +-- as needed to answer the requested queries. +getDefaultDistDir :: ProjLoc pt -> DistDir pt +getDefaultDistDir (ProjLocV1CabalFile _cabal_file pkgdir) = + DistDirCabal SCV1 $ pkgdir </> "dist" +getDefaultDistDir (ProjLocV1Dir pkgdir) = + DistDirCabal SCV1 $ pkgdir </> "dist" +getDefaultDistDir (ProjLocV2File cabal_project) = + DistDirCabal SCV2 $ replaceFileName cabal_project "dist-newstyle" +getDefaultDistDir (ProjLocV2Dir projdir) = + DistDirCabal SCV2 $ projdir </> "dist-newstyle" +getDefaultDistDir (ProjLocStackYaml _) = + DistDirStack Nothing + +-- | @isValidDistDir distdir@. Check if @distdir@ looks like a valid +-- build-dir for it's project type. We just check if characteristic marker +-- files for the associated project type exist. +-- +-- If the project type does not have a way to do this (for example +-- 'DistDirStack') check we return 'Nothing'. +isValidDistDir :: DistDir pt -> IO (Maybe Bool) +isValidDistDir (DistDirCabal cpt dir) = do + fmap Just $ doesFileExist $ dir </> cabalProjTypeMarkerFile cpt +isValidDistDir DistDirStack{} = + return Nothing -findCabalFiles :: FilePath -> IO [FilePath] -findCabalFiles dir = do - fs <- listDirectory dir - let cs = filter (".cabal" `isSuffixOf`) fs - filterM doesFileExist cs +cabalProjTypeMarkerFile :: SCabalProjType pt -> FilePath +cabalProjTypeMarkerFile SCV1 = "setup-config" +cabalProjTypeMarkerFile SCV2 = "cache" </> "plan.json" whenM :: Monad m => m Bool -> m () -> m () whenM p x = p >>= (`when` x) |