{-# 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 (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 (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 (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 (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 (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 (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 (m :: * -> *) a. Monad m => a -> m a
return Bool
False
         Left FileStoreError
RepositoryExists -> Bool -> IO Bool
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 (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Bool -> IO Bool
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 (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
                       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
                       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 (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 (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
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)
    -}