packages feed

yu-tool-0.1.1.30: src/Yu/Tool/Repo.hs

{-
 Copyright (C) 2017-2018 Johann Lee <me@qinka.pro>

 This file is part of Yu.

 Yu 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 3 of the License, or
 (at your option) any later version.

 Yu 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 Yu.  If not, see <http://www.gnu.org/licenses/>.
-}

{-|
Module:       Yu.Tool.Repo
Description:  Operations about repo.
Copyright:    (C) 2017-2018 Johann Lee
License:      GPL3
Maintainer:   me@qinka.pro
Stability:    experimental
Portability:  unknown

Operations about repo.
-}

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}
{-# LANGUAGE TemplateHaskell   #-}

module Yu.Tool.Repo
  ( RepoCfg(..)
  , Summary(..)
  , Item(..)
  , Nav(..)
  , findRepo
  , makeAbsoluteRepoT
  , makePathRelateRepo
  , yuRepoName
  , yuItemExt
  , yuRepoCfg
  , yuNavList
  ) where

import           Data.Char             (toLower)
import           Data.Function
import           Data.List
import           System.Directory
import           System.FilePath.Posix (makeRelative)
import           Yu.Import
import           Yu.Import.Aeson
import           Data.String
import qualified Yu.Import.Text        as T

newtype RepoCfg = RepoCfg { siteUrl :: String
                          }
                  deriving Show
deriveJSON defaultOptions{ fieldLabelModifier = map toLower
                         , constructorTagModifier = map toLower} ''RepoCfg

newtype Summary a = Summary (Either FilePath a)
                  deriving Show
deriveJSON defaultOptions ''Summary
instance Functor Summary where
  fmap f (Summary summary) = Summary $ f <$> summary

data Item a = Item { iSummary :: Summary a
                   , iMIME    :: Maybe a
                   , iPath    :: a
                   , iWhose   :: Maybe a
                   , iCreTime :: UTCTime
                   , iId      :: a
                   , iContent :: a
                   , iTitle   :: Maybe a
                   , iType    :: a
                   , iTags    :: [a]
                   }
          deriving Show
deriveJSON defaultOptions{ fieldLabelModifier = map toLower . drop 1
                         , constructorTagModifier = map toLower} ''Item
instance Functor Item where
  fmap f Item{..} = Item
                    (f <$> iSummary)
                    (f <$> iMIME)
                    (f     iPath)
                    (f <$> iWhose)
                    (      iCreTime)
                    (f     iId)
                    (f     iContent)
                    (f <$> iTitle)
                    (f     iType)
                    (f <$> iTags)


data Nav a = Nav { nOrder :: Int
                 , nUrl   :: a -- url
                 , nLabel :: a -- name, or say label
                 }
           deriving Show
instance Functor Nav where
  fmap f Nav{..} = Nav nOrder (f nUrl) (f nLabel)
instance Eq a => Eq (Nav a) where
  (==) = (==) `on` nLabel

deriveJSON defaultOptions{ fieldLabelModifier = map toLower . drop 1
                         , constructorTagModifier = map toLower} ''Nav

-- | find out repo's dir
--   If the path of the .git direcory is @/path/to/repo/.git@
--   @the findRepo ".git"@ will return @/path/to/repo@
findRepo :: FilePath -> IO (Maybe FilePath)
findRepo fp = getCurrentDirectory >>= findRepoStep
  where findRepoStep "" = return Nothing
        findRepoStep dir = do
          list <- filter (== fp) <$>  listDirectory dir
          if null list
            then findRepoStep (uplevel dir)
            else return (Just dir)
        uplevel "/" = ""
        uplevel p = reverse
                  . dropWhile (\x -> x /= '/' && x /= '\\')
                  . dropWhile (\x -> x == '/' || x == '\\')
                  . reverse
                  $ p

makeAbsoluteRepoT :: FilePath -- ^ repo
                  -> Item T.Text
                  -> Item T.Text
makeAbsoluteRepoT repo item =
  let newCon = T.pack repo `T.append` iContent item
      newSum = case iSummary item of
        Summary (Left p) -> Summary $ Left $ repo ++ p
        _                -> iSummary item
  in item { iSummary = newSum, iContent = newCon}

yuRepoName :: IsString a => a
yuRepoName = ".yu"

yuItemExt :: IsString a => a
yuItemExt = ".item.json"

yuRepoCfg :: IsString a => a
yuRepoCfg = "yual.json"

yuNavList :: IsString a => a
yuNavList = "navlist.json"

makePathRelateRepo :: FilePath -- ^ repo path
                   -> Item String
                   -> IO (Item String)
makePathRelateRepo repo item = do
  newSum <- case iSummary item of
        Summary (Left path) ->
          (Summary . Left . makeRelative repo) <$> makeAbsolute path
        _ -> return (iSummary item)
  newCon <- makeRelative repo <$> makeAbsolute (iContent item)
  return item{iSummary = newSum, iContent = newCon}