    {-# LANGUAGE CPP #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-
    Copyright (C) 2009 John MacFarlane <jgm@berkeley.edu>
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    -}

    {- | Functions for initializing a Gitit wiki.
    -}

    module Network.Gitit.Initialize ( initializeGititState
                                    , recompilePageTemplate
                                    , compilePageTemplate
                                    , createStaticIfMissing
                                    , createRepoIfMissing
                                    , createDefaultPages
                                    , createTemplateIfMissing )
    where
    import System.FilePath ((</>), (<.>))
    import Data.Semigroup ((<>))
    import Data.Text (Text)
    import qualified Data.Text as T
    import Data.FileStore
    import qualified Data.Map as M
    import Network.Gitit.Util (readFileUTF8)
    import Network.Gitit.Types
    import Network.Gitit.State
    import Network.Gitit.Framework
    import Network.Gitit.Plugins
    import Network.Gitit.Layout (defaultRenderPage)
    import Paths_gitit (getDataFileName)
    import Control.Exception (throwIO, try)
    import System.Directory (copyFile, createDirectoryIfMissing, doesDirectoryExist, doesFileExist)
    import Control.Monad ((<=<), unless, forM_, liftM)
    import Text.Pandoc hiding (getDataFileName, WARNING)
    import System.Log.Logger (logM, Priority(..))
    import qualified Text.StringTemplate as ST

    -- | Initialize Gitit State.
    initializeGititState :: Config -> IO ()
    initializeGititState :: Config -> IO ()
    initializeGititState Config
    conf = do
      let userFile' :: FilePath
    userFile' = Config -> FilePath
    userFile Config
    conf
          pluginModules' :: [FilePath]
    pluginModules' = Config -> [FilePath]
    pluginModules Config
    conf
      [Plugin]
    plugins' <- [FilePath] -> IO [Plugin]
    loadPlugins [FilePath]
    pluginModules'

      Bool
    userFileExists <- FilePath -> IO Bool
    doesFileExist FilePath
    userFile'
      Map FilePath User
    users' <- if Bool
    userFileExists
                   then (Text -> Map FilePath User) -> IO Text -> IO (Map FilePath User)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM ([(FilePath, User)] -> Map FilePath User
    forall k a. Ord k => [(k, a)] -> Map k a
    M.fromList ([(FilePath, User)] -> Map FilePath User)
    -> (Text -> [(FilePath, User)]) -> Text -> Map FilePath User
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> [(FilePath, User)]
    forall a. Read a => FilePath -> a
    read (FilePath -> [(FilePath, User)])
    -> (Text -> FilePath) -> Text -> [(FilePath, User)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> FilePath
    T.unpack) (IO Text -> IO (Map FilePath User))
    -> IO Text -> IO (Map FilePath User)
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO Text
    readFileUTF8 FilePath
    userFile'
                   else Map FilePath User -> IO (Map FilePath User)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Map FilePath User
    forall k a. Map k a
    M.empty

      StringTemplate FilePath
    templ <- FilePath -> IO (StringTemplate FilePath)
    compilePageTemplate (Config -> FilePath
    templatesDir Config
    conf)

      (GititState -> GititState) -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    (GititState -> GititState) -> m ()
    updateGititState ((GititState -> GititState) -> IO ())
    -> (GititState -> GititState) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \GititState
    s -> GititState
    s { sessions :: Sessions SessionData
    sessions      = Map SessionKey SessionData -> Sessions SessionData
    forall a. Map SessionKey a -> Sessions a
    Sessions Map SessionKey SessionData
    forall k a. Map k a
    M.empty
                                 , users :: Map FilePath User
    users         = Map FilePath User
    users'
                                 , templatesPath :: FilePath
    templatesPath = Config -> FilePath
    templatesDir Config
    conf
                                 , renderPage :: PageLayout -> Html -> Handler
    renderPage    = StringTemplate FilePath -> PageLayout -> Html -> Handler
    defaultRenderPage StringTemplate FilePath
    templ
                                 , plugins :: [Plugin]
    plugins       = [Plugin]
    plugins' }

    -- | Recompile the page template.
    recompilePageTemplate :: IO ()
    recompilePageTemplate :: IO ()
    recompilePageTemplate = do
      FilePath
    tempsDir <- (GititState -> FilePath) -> IO FilePath
    forall (m :: * -> *) a. MonadIO m => (GititState -> a) -> m a
    queryGititState GititState -> FilePath
    templatesPath
      StringTemplate FilePath
    ct <- FilePath -> IO (StringTemplate FilePath)
    compilePageTemplate FilePath
    tempsDir
      (GititState -> GititState) -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    (GititState -> GititState) -> m ()
    updateGititState ((GititState -> GititState) -> IO ())
    -> (GititState -> GititState) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \GititState
    st -> GititState
    st{renderPage :: PageLayout -> Html -> Handler
    renderPage = StringTemplate FilePath -> PageLayout -> Html -> Handler
    defaultRenderPage StringTemplate FilePath
    ct}

    --- | Compile a master page template named @page.st@ in the directory specified.
    compilePageTemplate :: FilePath -> IO (ST.StringTemplate String)
    compilePageTemplate :: FilePath -> IO (StringTemplate FilePath)
    compilePageTemplate FilePath
    tempsDir = do
      STGroup FilePath
    defaultGroup <- FilePath -> IO FilePath
    getDataFileName (FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "templates") IO FilePath
    -> (FilePath -> IO (STGroup FilePath)) -> IO (STGroup FilePath)
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= FilePath -> IO (STGroup FilePath)
    forall a. Stringable a => FilePath -> IO (STGroup a)
    ST.directoryGroup
      Bool
    customExists <- FilePath -> IO Bool
    doesDirectoryExist FilePath
    tempsDir
      STGroup FilePath
    combinedGroup <-
        if Bool
    customExists
           -- default templates from data directory will be "shadowed"
           -- by templates from the user's template dir
           then do STGroup FilePath
    customGroup <- FilePath -> IO (STGroup FilePath)
    forall a. Stringable a => FilePath -> IO (STGroup a)
    ST.directoryGroup FilePath
    tempsDir
                   STGroup FilePath -> IO (STGroup FilePath)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (STGroup FilePath -> IO (STGroup FilePath))
    -> STGroup FilePath -> IO (STGroup FilePath)
    forall a b. (a -> b) -> a -> b
    $ STGroup FilePath -> STGroup FilePath -> STGroup FilePath
    forall a. STGroup a -> STGroup a -> STGroup a
    ST.mergeSTGroups STGroup FilePath
    customGroup STGroup FilePath
    defaultGroup
           else do FilePath -> Priority -> FilePath -> IO ()
    logM FilePath
    "gitit" Priority
    WARNING (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "Custom template directory not found"
                   STGroup FilePath -> IO (STGroup FilePath)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return STGroup FilePath
    defaultGroup
      case FilePath -> STGroup FilePath -> Maybe (StringTemplate FilePath)
    forall a.
    Stringable a =>
    FilePath -> STGroup a -> Maybe (StringTemplate a)
    ST.getStringTemplate FilePath
    "page" STGroup FilePath
    combinedGroup of
            Just StringTemplate FilePath
    t    -> StringTemplate FilePath -> IO (StringTemplate FilePath)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return StringTemplate FilePath
    t
            Maybe (StringTemplate FilePath)
    Nothing   -> FilePath -> IO (StringTemplate FilePath)
    forall a. HasCallStack => FilePath -> a
    error FilePath
    "Could not get string template"

    -- | Create templates dir if it doesn't exist.
    createTemplateIfMissing :: Config -> IO ()
    createTemplateIfMissing :: Config -> IO ()
    createTemplateIfMissing Config
    conf' = do
      Bool
    templateExists <- FilePath -> IO Bool
    doesDirectoryExist (Config -> FilePath
    templatesDir Config
    conf')
      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless Bool
    templateExists (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
        Bool -> FilePath -> IO ()
    createDirectoryIfMissing Bool
    True (Config -> FilePath
    templatesDir Config
    conf')
        FilePath
    templatePath <- FilePath -> IO FilePath
    getDataFileName (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "templates"
        -- templs <- liftM (filter (`notElem` [".",".."])) $
        --  getDirectoryContents templatePath
        -- Copy footer.st, since this is the component users
        -- are most likely to want to customize:
        [FilePath] -> (FilePath -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [FilePath
    "footer.st"] ((FilePath -> IO ()) -> IO ()) -> (FilePath -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \FilePath
    t -> do
          FilePath -> FilePath -> IO ()
    copyFile (FilePath
    templatePath FilePath -> FilePath -> FilePath
    </> FilePath
    t) (Config -> FilePath
    templatesDir Config
    conf' FilePath -> FilePath -> FilePath
    </> FilePath
    t)
          FilePath -> Priority -> FilePath -> IO ()
    logM FilePath
    "gitit" Priority
    WARNING (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "Created " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ (Config -> FilePath
    templatesDir Config
    conf' FilePath -> FilePath -> FilePath
    </> FilePath
    t)

    -- | Create page repository unless it exists.
    createRepoIfMissing :: Config -> IO ()
    createRepoIfMissing :: Config -> IO ()
    createRepoIfMissing Config
    conf = do
      let fs :: FileStore
    fs = Config -> FileStore
    filestoreFromConfig Config
    conf
      Bool
    repoExists <- IO () -> IO (Either FileStoreError ())
    forall e a. Exception e => IO a -> IO (Either e a)
    try (FileStore -> IO ()
    initialize FileStore
    fs) IO (Either FileStoreError ())
    -> (Either FileStoreError () -> IO Bool) -> IO Bool
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Either FileStoreError ()
    res ->
        case Either FileStoreError ()
    res of
             Right ()
    _               -> do
               FilePath -> Priority -> FilePath -> IO ()
    logM FilePath
    "gitit" Priority
    WARNING (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "Created repository in " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ Config -> FilePath
    repositoryPath Config
    conf
               Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
             Left FileStoreError
    RepositoryExists -> Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    True
             Left FileStoreError
    e                -> FileStoreError -> IO Any
    forall e a. Exception e => e -> IO a
    throwIO FileStoreError
    e IO Any -> IO Bool -> IO Bool
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless Bool
    repoExists (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Config -> IO ()
    createDefaultPages Config
    conf

    createDefaultPages :: Config -> IO ()
    createDefaultPages :: Config -> IO ()
    createDefaultPages Config
    conf = do
        let fs :: FileStore
    fs = Config -> FileStore
    filestoreFromConfig Config
    conf
            pt :: PageType
    pt = Config -> PageType
    defaultPageType Config
    conf
            toPandoc :: Text -> PandocPure Pandoc
    toPandoc = ReaderOptions -> Text -> PandocPure Pandoc
    forall (m :: * -> *) a.
    (PandocMonad m, ToSources a) =>
    ReaderOptions -> a -> m Pandoc
    readMarkdown ReaderOptions
    forall a. Default a => a
    def{ readerExtensions :: Extensions
    readerExtensions = Extension -> Extensions -> Extensions
    enableExtension Extension
    Ext_smart (ReaderOptions -> Extensions
    readerExtensions ReaderOptions
    forall a. Default a => a
    def) }
            defOpts :: WriterOptions
    defOpts = WriterOptions
    forall a. Default a => a
    def{ writerExtensions :: Extensions
    writerExtensions = if Config -> Bool
    showLHSBirdTracks Config
    conf
                                                 then Extension -> Extensions -> Extensions
    enableExtension
                                                      Extension
    Ext_literate_haskell
                                                      (Extensions -> Extensions) -> Extensions -> Extensions
    forall a b. (a -> b) -> a -> b
    $ WriterOptions -> Extensions
    writerExtensions WriterOptions
    forall a. Default a => a
    def
                                                 else WriterOptions -> Extensions
    writerExtensions WriterOptions
    forall a. Default a => a
    def
                         }
            -- note: we convert this (markdown) to the default page format
            converter :: Text -> IO Text
    converter = Either PandocError Text -> IO Text
    forall a. Either PandocError a -> IO a
    handleError (Either PandocError Text -> IO Text)
    -> (Text -> Either PandocError Text) -> Text -> IO Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PandocPure Text -> Either PandocError Text
    forall a. PandocPure a -> Either PandocError a
    runPure (PandocPure Text -> Either PandocError Text)
    -> (Text -> PandocPure Text) -> Text -> Either PandocError Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . case PageType
    pt of
                           PageType
    Markdown   -> Text -> PandocPure Text
    forall a. a -> PandocPure a
    forall (m :: * -> *) a. Monad m => a -> m a
    return
                           PageType
    LaTeX      -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeLaTeX WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
                           PageType
    HTML       -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeHtml5String WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
                           PageType
    RST        -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeRST WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
                           PageType
    Textile    -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeTextile WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
                           PageType
    Org        -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeOrg WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
    #if MIN_VERSION_pandoc(3,0,0)
                           PageType
    DocBook    -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeDocBook5 WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
    #else
                           DocBook    -> writeDocbook5 defOpts <=< toPandoc
    #endif
                           PageType
    MediaWiki  -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeMediaWiki WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc
                           PageType
    CommonMark -> WriterOptions -> Pandoc -> PandocPure Text
    forall (m :: * -> *).
    PandocMonad m =>
    WriterOptions -> Pandoc -> m Text
    writeCommonMark WriterOptions
    defOpts (Pandoc -> PandocPure Text)
    -> (Text -> PandocPure Pandoc) -> Text -> PandocPure Text
    forall (m :: * -> *) b c a.
    Monad m =>
    (b -> m c) -> (a -> m b) -> a -> m c
    <=< Text -> PandocPure Pandoc
    toPandoc

        FilePath
    welcomepath <- FilePath -> IO FilePath
    getDataFileName (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "FrontPage" FilePath -> FilePath -> FilePath
    <.> FilePath
    "page"
        Text
    welcomecontents <- Text -> IO Text
    converter (Text -> IO Text) -> IO Text -> IO Text
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< FilePath -> IO Text
    readFileUTF8 FilePath
    welcomepath
        FilePath
    helppath <- FilePath -> IO FilePath
    getDataFileName (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "Help" FilePath -> FilePath -> FilePath
    <.> FilePath
    "page"
        Text
    helpcontentsInitial <- Text -> IO Text
    converter (Text -> IO Text) -> IO Text -> IO Text
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< FilePath -> IO Text
    readFileUTF8 FilePath
    helppath
        FilePath
    markuppath <- FilePath -> IO FilePath
    getDataFileName (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "markup" FilePath -> FilePath -> FilePath
    <.> PageType -> FilePath
    forall a. Show a => a -> FilePath
    show PageType
    pt
        Text
    helpcontentsMarkup <- Text -> IO Text
    converter (Text -> IO Text) -> IO Text -> IO Text
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< FilePath -> IO Text
    readFileUTF8 FilePath
    markuppath
        let helpcontents :: Text
    helpcontents = Text
    helpcontentsInitial Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "\n\n" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    helpcontentsMarkup
        FilePath
    usersguidepath <- FilePath -> IO FilePath
    getDataFileName FilePath
    "README.markdown"
        Text
    usersguidecontents <- Text -> IO Text
    converter (Text -> IO Text) -> IO Text -> IO Text
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< FilePath -> IO Text
    readFileUTF8 FilePath
    usersguidepath
        -- include header in case user changes default format:
        let header :: Text
    header = Text
    "---\nformat: " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
              FilePath -> Text
    T.pack (PageType -> FilePath
    forall a. Show a => a -> FilePath
    show PageType
    pt) Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> (if Config -> Bool
    defaultLHS Config
    conf then Text
    "+lhs" else Text
    "") Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
              Text
    "\n...\n\n"
        -- add front page, help page, and user's guide
        let auth :: Author
    auth = FilePath -> FilePath -> Author
    Author FilePath
    "Gitit" FilePath
    ""
        FileStore -> FilePath -> Author -> FilePath -> Text -> IO ()
    createIfMissing FileStore
    fs (Config -> FilePath
    frontPage Config
    conf FilePath -> FilePath -> FilePath
    <.> Config -> FilePath
    defaultExtension Config
    conf) Author
    auth FilePath
    "Default front page"
          (Text -> IO ()) -> Text -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Text
    header Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    welcomecontents
        FileStore -> FilePath -> Author -> FilePath -> Text -> IO ()
    createIfMissing FileStore
    fs (FilePath
    "Help" FilePath -> FilePath -> FilePath
    <.> Config -> FilePath
    defaultExtension Config
    conf) Author
    auth FilePath
    "Default help page"
          (Text -> IO ()) -> Text -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Text
    header Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    helpcontents
        FileStore -> FilePath -> Author -> FilePath -> Text -> IO ()
    createIfMissing FileStore
    fs (FilePath
    "Gitit User’s Guide" FilePath -> FilePath -> FilePath
    <.> Config -> FilePath
    defaultExtension Config
    conf) Author
    auth FilePath
    "User’s guide (README)"
          (Text -> IO ()) -> Text -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Text
    header Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    usersguidecontents

    createIfMissing :: FileStore -> FilePath -> Author -> Description -> Text -> IO ()
    createIfMissing :: FileStore -> FilePath -> Author -> FilePath -> Text -> IO ()
    createIfMissing FileStore
    fs FilePath
    p Author
    a FilePath
    comm Text
    cont = do
      Either FileStoreError ()
    res <- IO () -> IO (Either FileStoreError ())
    forall e a. Exception e => IO a -> IO (Either e a)
    try (IO () -> IO (Either FileStoreError ()))
    -> IO () -> IO (Either FileStoreError ())
    forall a b. (a -> b) -> a -> b
    $ FileStore -> FilePath -> Author -> FilePath -> FilePath -> IO ()
    forall a.
    Contents a =>
    FileStore -> FilePath -> Author -> FilePath -> a -> IO ()
    create FileStore
    fs FilePath
    p Author
    a FilePath
    comm (Text -> FilePath
    T.unpack Text
    cont)
      case Either FileStoreError ()
    res of
           Right ()
    _ -> FilePath -> Priority -> FilePath -> IO ()
    logM FilePath
    "gitit" Priority
    WARNING (FilePath
    "Added " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    p FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    " to repository")
           Left FileStoreError
    ResourceExists -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
           Left FileStoreError
    e              -> FileStoreError -> IO Any
    forall e a. Exception e => e -> IO a
    throwIO FileStoreError
    e IO Any -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    -- | Create static directory unless it exists.
    createStaticIfMissing :: Config -> IO ()
    createStaticIfMissing :: Config -> IO ()
    createStaticIfMissing Config
    conf = do
      let staticdir :: FilePath
    staticdir = Config -> FilePath
    staticDir Config
    conf
      Bool
    staticExists <- FilePath -> IO Bool
    doesDirectoryExist FilePath
    staticdir
      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless Bool
    staticExists (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do

        let cssdir :: FilePath
    cssdir = FilePath
    staticdir FilePath -> FilePath -> FilePath
    </> FilePath
    "css"
        Bool -> FilePath -> IO ()
    createDirectoryIfMissing Bool
    True FilePath
    cssdir
        FilePath
    cssDataDir <- FilePath -> IO FilePath
    getDataFileName (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "static" FilePath -> FilePath -> FilePath
    </> FilePath
    "css"
        -- cssFiles <- liftM (filter (\f -> takeExtension f == ".css")) $ getDirectoryContents cssDataDir
        [FilePath] -> (FilePath -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [FilePath
    "custom.css"] ((FilePath -> IO ()) -> IO ()) -> (FilePath -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \FilePath
    f -> do
          FilePath -> FilePath -> IO ()
    copyFile (FilePath
    cssDataDir FilePath -> FilePath -> FilePath
    </> FilePath
    f) (FilePath
    cssdir FilePath -> FilePath -> FilePath
    </> FilePath
    f)
          FilePath -> Priority -> FilePath -> IO ()
    logM FilePath
    "gitit" Priority
    WARNING (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "Created " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ (FilePath
    cssdir FilePath -> FilePath -> FilePath
    </> FilePath
    f)

        {-
        let icondir = staticdir </> "img" </> "icons"
        createDirectoryIfMissing True icondir
        iconDataDir <- getDataFileName $ "data" </> "static" </> "img" </> "icons"
        iconFiles <- liftM (filter (\f -> takeExtension f == ".png")) $ getDirectoryContents iconDataDir
        forM_ iconFiles $ \f -> do
          copyFile (iconDataDir </> f) (icondir </> f)
          logM "gitit" WARNING $ "Created " ++ (icondir </> f)
        -}

        FilePath
    logopath <- FilePath -> IO FilePath
    getDataFileName (FilePath -> IO FilePath) -> FilePath -> IO FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "data" FilePath -> FilePath -> FilePath
    </> FilePath
    "static" FilePath -> FilePath -> FilePath
    </> FilePath
    "img" FilePath -> FilePath -> FilePath
    </> FilePath
    "logo.png"
        Bool -> FilePath -> IO ()
    createDirectoryIfMissing Bool
    True (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    staticdir FilePath -> FilePath -> FilePath
    </> FilePath
    "img"
        FilePath -> FilePath -> IO ()
    copyFile FilePath
    logopath (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    staticdir FilePath -> FilePath -> FilePath
    </> FilePath
    "img" FilePath -> FilePath -> FilePath
    </> FilePath
    "logo.png"
        FilePath -> Priority -> FilePath -> IO ()
    logM FilePath
    "gitit" Priority
    WARNING (FilePath -> IO ()) -> FilePath -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "Created " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ (FilePath
    staticdir FilePath -> FilePath -> FilePath
    </> FilePath
    "img" FilePath -> FilePath -> FilePath
    </> FilePath
    "logo.png")

        {-
        let jsdir = staticdir </> "js"
        createDirectoryIfMissing True jsdir
        jsDataDir <- getDataFileName $ "data" </> "static" </> "js"
        javascripts <- liftM (filter (`notElem` [".", ".."])) $ getDirectoryContents jsDataDir
        forM_ javascripts $ \f -> do
          copyFile (jsDataDir </> f) (jsdir </> f)
          logM "gitit" WARNING $ "Created " ++ (jsdir </> f)
        -}