module Main where
import Control.Monad
import Data.List
import Distribution.PackageDescription (PackageDescription (..))
import Distribution.Simple
import Distribution.Simple.Install
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Setup
import Distribution.Simple.Utils
import System.FilePath
-- | Run cabal with custom copyHook which puts our extra executables in the
-- libexec directory.
main :: IO ()
main = defaultMainWithHooks $ simpleUserHooks
{ copyHook = copyThings
}
-- | Copy "extra" executables to $PREFIX/libexec/git-vogue/ instead of
-- $PREFIX/bin.
copyThings
:: PackageDescription
-> LocalBuildInfo
-> UserHooks
-> CopyFlags
-> IO ()
copyThings pkg lbi _ flags = do
-- First install only the "main" components with the default settings.
let (main_pkg, main_lbi) = tweakMainInstall pkg lbi
install main_pkg main_lbi flags
-- Then install the "secondary" executables and plugin scripts with the
-- special settings.
let (sub_pkg, sub_lbi) = tweakSubcommandInstall pkg lbi
install sub_pkg sub_lbi flags
-- Install shell scripts from plugins/.
--
-- This was stolen from "Distribution.Simple.Install" and hacked. Why is
-- cabal so terrible compared to make and friends?
let scripts = fmap stripPluginPrefix . filter isPlugin $ dataFiles pkg
verbosity = fromFlag (copyVerbosity flags)
src_data_dir = dataDir sub_pkg
dest_data_dir = datadir . absoluteInstallDirs sub_pkg sub_lbi $
fromFlag (copyDest flags)
forM_ scripts $ \ file -> do
let dir = takeDirectory file
files <- matchDirFileGlob src_data_dir file
createDirectoryIfMissingVerbose verbosity True (dest_data_dir </> dir)
forM_ files $ \file' ->
installExecutableFile verbosity (src_data_dir </> file')
(dest_data_dir </> file')
-- | Directory our plugin scripts are kept in.
pluginPrefix :: FilePath
pluginPrefix = "plugins/"
-- | Strip the 'pluginPrefix' off the front of a 'FilePath'.
stripPluginPrefix :: FilePath -> FilePath
stripPluginPrefix = dropWhile (== '/') . dropWhile (/= '/')
-- | A data file is in the plugins directory.
isPlugin :: FilePath -> Bool
isPlugin = (pluginPrefix `isPrefixOf`)
-- | Tweak parameters for install of main components (i.e. library and first
-- executable) only.
tweakMainInstall
:: PackageDescription
-> LocalBuildInfo
-> (PackageDescription, LocalBuildInfo)
tweakMainInstall pkg lbi =
let pkg' = pkg { executables = take 1 $ executables pkg
, dataFiles = filter (not . isPlugin) $ dataFiles pkg
}
in (pkg', lbi)
-- | Tweak parameters for install of secondary components (i.e. executables
-- other than the first.
tweakSubcommandInstall
:: PackageDescription
-> LocalBuildInfo
-> (PackageDescription, LocalBuildInfo)
tweakSubcommandInstall pkg lbi =
let dest = suffixIt . libexecdir $ installDirTemplates lbi
pkg' = pkg { executables = tail $ executables pkg
, dataFiles = []
, dataDir = dataDir pkg </> pluginPrefix
, library = Nothing
, testSuites = []
, benchmarks = []
, extraSrcFiles = []
, extraTmpFiles = []
, extraDocFiles = []
}
lbi' = lbi { installDirTemplates = (installDirTemplates lbi)
{ bindir = dest
, datadir = dest
, datasubdir = toPathTemplate ""
}
}
in (pkg', lbi')
where
suffixIt = toPathTemplate . (</> "git-vogue") . fromPathTemplate