-- | List those source files that should be copied with ordinary permissions.
listPackageSourcesOrdinary :: Verbosity
                           -> PackageDescription
                           -> [PPSuffixHandler]
                           -> IO [FilePath]
listPackageSourcesOrdinary verbosity pkg_descr pps =
  fmap concat . sequence $
  [
    -- Library sources.
    fmap concat
    . withAllLib $ \Library { exposedModules = modules, libBuildInfo = libBi } ->
     allSourcesBuildInfo libBi pps modules

    -- Executables sources.
  , fmap concat
    . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do
       biSrcs  <- allSourcesBuildInfo exeBi pps []
       mainSrc <- findMainExeFile exeBi pps mainPath
       return (mainSrc:biSrcs)

    -- Test suites sources.
  , fmap concat
    . withAllTest $ \t -> do
       let bi  = testBuildInfo t
       case testInterface t of
         TestSuiteExeV10 _ mainPath -> do
           biSrcs <- allSourcesBuildInfo bi pps []
           srcMainFile <- do
             ppFile <- findFileWithExtension (ppSuffixes pps)
                       (hsSourceDirs bi) (dropExtension mainPath)
             case ppFile of
               Nothing -> findFile (hsSourceDirs bi) mainPath
               Just pp -> return pp
           return (srcMainFile:biSrcs)
         TestSuiteLibV09 _ m ->
           allSourcesBuildInfo bi pps [m]
         TestSuiteUnsupported tp -> die $ "Unsupported test suite type: "
                                   ++ show tp

    -- Benchmarks sources.
  , fmap concat
    . withAllBenchmark $ \bm -> do
       let  bi = benchmarkBuildInfo bm
       case benchmarkInterface bm of
         BenchmarkExeV10 _ mainPath -> do
           biSrcs <- allSourcesBuildInfo bi pps []
           srcMainFile <- do
             ppFile <- findFileWithExtension (ppSuffixes pps)
                       (hsSourceDirs bi) (dropExtension mainPath)
             case ppFile of
               Nothing -> findFile (hsSourceDirs bi) mainPath
               Just pp -> return pp
           return (srcMainFile:biSrcs)
         BenchmarkUnsupported tp -> die $ "Unsupported benchmark type: "
                                    ++ show tp

    -- Data files.
  , fmap concat
    . forM (dataFiles pkg_descr) $ \filename ->
       matchFileGlob (dataDir pkg_descr </> filename)

    -- Extra doc files.
  , fmap concat
    . forM (extraDocFiles pkg_descr) $ \ filename ->
      matchFileGlob filename

    -- License file(s).
  , return (licenseFiles pkg_descr)

    -- Install-include files.
  , fmap concat
    . withAllLib $ \ l -> do
       let lbi = libBuildInfo l
           relincdirs = "." : filter (not.isAbsolute) (includeDirs lbi)
       mapM (fmap snd . findIncludeFile relincdirs) (installIncludes lbi)

    -- Setup script, if it exists.
  , fmap (maybe [] (\f -> [f])) $ findSetupFile ""

    -- The .cabal file itself.
  , fmap (\d -> [d]) (defaultPackageDesc verbosity)

  ]
  where
    -- We have to deal with all libs and executables, so we have local
    -- versions of these functions that ignore the 'buildable' attribute:
    withAllLib       action = mapM action (libraries pkg_descr)
    withAllExe       action = mapM action (executables pkg_descr)
    withAllTest      action = mapM action (testSuites pkg_descr)
    withAllBenchmark action = mapM action (benchmarks pkg_descr)


-- |Prepare a directory tree of source files.
listPackageSourcesOrdinary :: Verbosity
                           -> PackageDescription
                           -> [PPSuffixHandler]
                           -> IO [FilePath]
listPackageSourcesOrdinary verbosity pkg_descr pps =
  fmap concat . sequence $
  [
    -- Library sources.
    fmap concat
    . withAllLib $ \Library { exposedModules = modules, libBuildInfo = libBi } ->
     allSourcesBuildInfo libBi pps modules

    -- Executables sources.
  , fmap concat
    . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do
       biSrcs  <- allSourcesBuildInfo exeBi pps []
       mainSrc <- findMainExeFile exeBi pps mainPath
       return (mainSrc:biSrcs)

    -- Test suites sources.
  , fmap concat
    . withAllTest $ \t -> do
       let bi  = testBuildInfo t
       case testInterface t of
         TestSuiteExeV10 _ mainPath -> do
           biSrcs <- allSourcesBuildInfo bi pps []
           srcMainFile <- do
             ppFile <- findFileWithExtension (ppSuffixes pps)
                       (hsSourceDirs bi) (dropExtension mainPath)
             case ppFile of
               Nothing -> findFile (hsSourceDirs bi) mainPath
               Just pp -> return pp
           return (srcMainFile:biSrcs)
         TestSuiteLibV09 _ m ->
           allSourcesBuildInfo bi pps [m]
         TestSuiteUnsupported tp -> die $ "Unsupported test suite type: "
                                   ++ show tp

    -- Benchmarks sources.
  , fmap concat
    . withAllBenchmark $ \bm -> do
       let  bi = benchmarkBuildInfo bm
       case benchmarkInterface bm of
         BenchmarkExeV10 _ mainPath -> do
           biSrcs <- allSourcesBuildInfo bi pps []
           srcMainFile <- do
             ppFile <- findFileWithExtension (ppSuffixes pps)
                       (hsSourceDirs bi) (dropExtension mainPath)
             case ppFile of
               Nothing -> findFile (hsSourceDirs bi) mainPath
               Just pp -> return pp
           return (srcMainFile:biSrcs)
         BenchmarkUnsupported tp -> die $ "Unsupported benchmark type: "
                                    ++ show tp

    -- Data files.
  , fmap concat
    . forM (dataFiles pkg_descr) $ \filename ->
       matchFileGlob (dataDir pkg_descr </> filename)

    -- Extra doc files.
  , fmap concat
    . forM (extraDocFiles pkg_descr) $ \ filename ->
      matchFileGlob filename

    -- License file(s).
  , return (licenseFiles pkg_descr)

    -- Install-include files.
  , fmap concat
    . withAllLib $ \ l -> do
       let lbi = libBuildInfo l
           relincdirs = "." : filter (not.isAbsolute) (includeDirs lbi)
       mapM (fmap snd . findIncludeFile relincdirs) (installIncludes lbi)

    -- Setup script, if it exists.
  , fmap (maybe [] (\f -> [f])) $ findSetupFile ""

    -- The .cabal file itself.
  , fmap (\d -> [d]) (defaultPackageDesc verbosity)

  ]
  where
    -- We have to deal with all libs and executables, so we have local
    -- versions of these functions that ignore the 'buildable' attribute:
    withAllLib       action = mapM action (libraries pkg_descr)
    withAllExe       action = mapM action (executables pkg_descr)
    withAllTest      action = mapM action (testSuites pkg_descr)
    withAllBenchmark action = mapM action (benchmarks pkg_descr)


-- |Prepare a directory tree of source files.
listPackageSourcesOrdinary verbosity pkg_descr pps =
  fmap concat . sequence $
  [
    -- Library sources.
    fmap concat
    . withAllLib $ \Library { exposedModules = modules, libBuildInfo = libBi } ->
     allSourcesBuildInfo libBi pps modules

    -- Executables sources.
  , fmap concat
    . withAllExe $ \Executable { modulePath = mainPath, buildInfo = exeBi } -> do
       biSrcs  <- allSourcesBuildInfo exeBi pps []
       mainSrc <- findMainExeFile exeBi pps mainPath
       return (mainSrc:biSrcs)

    -- Test suites sources.
  , fmap concat
    . withAllTest $ \t -> do
       let bi  = testBuildInfo t
       case testInterface t of
         TestSuiteExeV10 _ mainPath -> do
           biSrcs <- allSourcesBuildInfo bi pps []
           srcMainFile <- do
             ppFile <- findFileWithExtension (ppSuffixes pps)
                       (hsSourceDirs bi) (dropExtension mainPath)
             case ppFile of
               Nothing -> findFile (hsSourceDirs bi) mainPath
               Just pp -> return pp
           return (srcMainFile:biSrcs)
         TestSuiteLibV09 _ m ->
           allSourcesBuildInfo bi pps [m]
         TestSuiteUnsupported tp -> die $ "Unsupported test suite type: "
                                   ++ show tp

    -- Benchmarks sources.
  , fmap concat
    . withAllBenchmark $ \bm -> do
       let  bi = benchmarkBuildInfo bm
       case benchmarkInterface bm of
         BenchmarkExeV10 _ mainPath -> do
           biSrcs <- allSourcesBuildInfo bi pps []
           srcMainFile <- do
             ppFile <- findFileWithExtension (ppSuffixes pps)
                       (hsSourceDirs bi) (dropExtension mainPath)
             case ppFile of
               Nothing -> findFile (hsSourceDirs bi) mainPath
               Just pp -> return pp
           return (srcMainFile:biSrcs)
         BenchmarkUnsupported tp -> die $ "Unsupported benchmark type: "
                                    ++ show tp

    -- Data files.
  , fmap concat
    . forM (dataFiles pkg_descr) $ \filename ->
       matchFileGlob (dataDir pkg_descr </> filename)

    -- Extra doc files.
  , fmap concat
    . forM (extraDocFiles pkg_descr) $ \ filename ->
      matchFileGlob filename

    -- License file(s).
  , return (licenseFiles pkg_descr)

    -- Install-include files.
  , fmap concat
    . withAllLib $ \ l -> do
       let lbi = libBuildInfo l
           relincdirs = "." : filter (not.isAbsolute) (includeDirs lbi)
       mapM (fmap snd . findIncludeFile relincdirs) (installIncludes lbi)

    -- Setup script, if it exists.
  , fmap (maybe [] (\f -> [f])) $ findSetupFile ""

    -- The .cabal file itself.
  , fmap (\d -> [d]) (defaultPackageDesc verbosity)

  ]
  where
    -- We have to deal with all libs and executables, so we have local
    -- versions of these functions that ignore the 'buildable' attribute:
    withAllLib       action = mapM action (libraries pkg_descr)
    withAllExe       action = mapM action (executables pkg_descr)
    withAllTest      action = mapM action (testSuites pkg_descr)
    withAllBenchmark action = mapM action (benchmarks pkg_descr)


-- |Prepare a directory tree of source files.