packages feed

bamse-0.9.1: Bamse/Builder.hs

--
-- (c) 2007, Galois, Inc.
--
-- Toplevel module for bamse library/app.
-- 
-- Bamse - a batch MSI installer creator.
--
-- ToDo:
--     - ability to organise installed bits into features/sub parts.
-- 
module Bamse.Builder ( genBuilder ) where

import Bamse.Package
import Bamse.Writer
import Bamse.IMonad
import Bamse.PackageGen
import Bamse.MSIExtra
import Bamse.PackageUtils
import Bamse.DialogUtils

import System.Win32.Com ( coRun )
import IO
import Util.Path ( dirname, appendSep, toPlatformPath, joinPath, splitPath, appendPath )
import Util.Dir
import Util.List ( ifCons )

import System 
import IO
import Monad   ( when )
import Maybe
import Bamse.Options
import System.Directory

genBuilder :: PackageData -> IO ()
genBuilder pkg = do
  putStrLn ("Installer builder for: " ++ name (p_pkgInfo pkg)) >> hFlush stdout
  opts           <- getOptions (p_defOutFile pkg)
  ds             <- (p_fileMap pkg) (opt_ienv opts)
  (dsDist, ienv) <- mkDistTree (opt_ienv opts)        (srcDir $ opt_ienv opts)
  			       (name $ p_pkgInfo pkg) (p_distFileMap pkg)
  			       ds
  let pkg' = pkg{ p_files   = dsDist
		, p_dialogs = 
		       (if p_userInstall pkg
		         then (setupTypeDialog:)
			 else if isJust (p_ghcPackage pkg)
			  then (ghcPkgDialog:)
			  else id) $
			   -- add customization selection dialog only if the
			   -- builder supplies the relevant features.
			  case options (opt_ienv opts) of
			    [] -> []
			    os -> [customizeDialog os]
  		, p_productGUID  = fromJust (opt_productGUID opts)
		, p_revisionGUID = fromJust (opt_revisionGUID opts)
		, p_ienv         = opt_ienv opts
		, p_verbose      = opt_verbose opts
  		}
  let bamseDir = toolDir (p_ienv pkg')
  coRun $ do
    (_, ts, tabs, reps) <-  doInstall [] (genTables pkg')
    let env = 
         WriterEnv 
            { w_toolDir     = bamseDir
   	    , w_templateDir = lFile (lFile bamseDir "data") "msi"
	    , w_outFile     = outFile (p_ienv pkg')
	    , w_srcDir      = dirname (srcDir $ p_ienv pkg')
	    , w_package     = pkg'
	    }
    outputMSI env tabs ts reps
    return ()
 where
  options ienv
   = ifCons (not (null (p_extensions pkg ienv)))
   	    ("Register file extensions", "OptFileExt", True) $
       ifCons (not (null (p_desktopShortcuts pkg ienv)))
              ("Create desktop shortcuts", "OptDesktopShortcuts", True) $
	 ifCons (not (null (snd $ p_startMenu pkg ienv)))
	        ("Create start menu folder", "OptStartMenu", True)
		[]


mkDistTree :: InstallEnv
	   -> FilePath
	   -> String
	   -> Maybe (FilePath -> Maybe FilePath)
	   -> DirTree
	   -> IO (DirTree, InstallEnv)
mkDistTree ienv _      _  Nothing   ds = return (ds, ienv)
mkDistTree ienv topDir nm (Just fn) ds = do
     -- copy over directory tree into temporary 'outDir'
    fp <- getCurrentDirectory
    catch (createDirectory (appendP fp "out")) (\ _ -> return ())
    let outDir = appendP fp (appendP "out" nm)
    catch (createDirectory outDir) (\ _ -> return ())
    copyOver outDir ds
    ds <- allFiles outDir
    return (ds, ienv{srcDir=outDir})
  where
    copyOver _ Empty         = return ()
    copyOver outDir (File f) = do
      case fn f of
        Nothing -> return ()
	Just f  -> do
          let cmd = ("copy /b \"" ++ f ++ "\" \"" ++ 
	             appendP outDir (dropDirPrefix topDir f) ++ "\" > nul")
          system cmd
          return ()
    copyOver outDir (Directory fp subs) = do
       case fn fp of
         Nothing -> return ()
	 Just fp -> system ("mkdir " ++ appendP outDir (dropDirPrefix topDir fp)) >> return ()
       mapM_ (copyOver outDir) subs

    appendP a b = toPlatformPath $ appendPath a b