----------------------------------------------------------------------------- -- | -- Module : Static.Resources.Checked -- Copyright : (c) Scrive 2012 -- License : BSD-style (see the LICENSE file in the distribution) -- -- Maintainer : mariusz@scrive.com -- Stability : development -- Portability : portable -- -- Basic consistency checker. module Static.Resources.Checker ( -- * Checker check, isStaticResourceFile ) where import System.IO.HVFS.Utils import Data.List import Control.Monad import Static.Resources.Types import Data.Functor import Control.Monad.Error import System.Directory -- | Performs check. Left is error with some description. -- * Fails with css and js files avaible but not listed in spec. -- * Fails with css and js files that are in spec, but not avaible. check :: String -> ResourceSpec -> IO (Either String ()) check dir spec = do sysFiles <- mapM canonicalizePath =<< filter isStaticResourceFile <$> recurseDir SystemFS dir specFiles <- mapM (\r -> canonicalizePath $ dir ++ "/" ++ path r) $ (join $ resources <$> sets spec) ignoredFiles <- mapM (\p -> canonicalizePath $ dir ++ "/" ++ p) $ ignored spec let diff a b = fileDiff (sort $ nub a) (sort $ nub b) runErrorT $ do when (not $ null $ diff sysFiles (specFiles ++ ignoredFiles)) $ throwError $ "Files from some sets are not availble in FS: \n" ++ (unlines $ diff sysFiles (specFiles ++ ignoredFiles)) ++ "\n\n" when (not $ null $ diff (specFiles ++ ignoredFiles) sysFiles) $ throwError $ "Some files on filesystem are not listed in any set or ignored: \n" ++ (unlines $ diff (specFiles ++ ignoredFiles) sysFiles) ++ "\n\n" -- | Difference between two sets. Simillar to -, but with some respect to dirs. fileDiff:: [FilePath] -> [FilePath] -> [FilePath] fileDiff (f1:f1s) (f2:f2s) | (isDir f1 && f1 `isPrefixOf` f2) = fileDiff (f1:f1s) f2s | (isDir f2 && f2 `isPrefixOf` f1) = fileDiff f1s (f2 : f2s) | (f1 == f2) = fileDiff f1s f2s | (f1 <= f2) && (isDir f1) = fileDiff f1s (f2:f2s) | (f1 <= f2) = f1 : (fileDiff f1s (f2:f2s)) | otherwise = fileDiff (f1:f1s) f2s fileDiff [] fs = filter (not . isDir) fs fileDiff _ _ = [] isDir :: String -> Bool isDir = not . isStaticResourceFile isStaticResourceFile :: String -> Bool isStaticResourceFile fn = any (`isSuffixOf` fn) [".css",".js",".less"]