1 module Rakka.Storage.Repos
2 ( findAllPagesInRevision
3 , findChangedPagesAtRevision
10 import qualified Data.Map as M
13 import qualified Data.Set as S hiding (Set)
15 import Network.HTTP.Lucu hiding (redirect)
17 import Rakka.SystemConfig
19 import Rakka.W3CDateTime
20 import Subversion.Types
21 import Subversion.FileSystem
22 import Subversion.FileSystem.DirEntry
23 import Subversion.FileSystem.Revision
24 import Subversion.FileSystem.Root
25 import Subversion.Repository
26 import System.FilePath.Posix
29 findAllPagesInRevision :: Repository -> RevNum -> IO (Set PageName)
30 findAllPagesInRevision repos rev
31 = do fs <- getRepositoryFS repos
33 $ do exists <- isDirectory root
42 traverse :: FilePath -> Rev (Set PageName)
44 = getDirEntries dir >>= mapM (traverse' dir) >>= return . S.unions
46 traverse' :: FilePath -> DirEntry -> Rev (Set PageName)
48 = let path = dir </> entName entry
50 do kind <- checkPath path
52 NoNode -> return S.empty
53 FileNode -> return $ S.singleton (decodePath path)
54 DirNode -> traverse path
56 decodePath :: FilePath -> PageName
57 decodePath = decodePageName . makeRelative root . dropExtension
60 findChangedPagesAtRevision :: Repository -> RevNum -> IO (Set PageName)
61 findChangedPagesAtRevision repos rev
62 = do fs <- getRepositoryFS repos
64 $ getPathsChanged >>= return . foldl accumulatePages S.empty . map fst
66 accumulatePages :: Set PageName -> FilePath -> Set PageName
67 accumulatePages s path
68 | "/pages/" `isPrefixOf` path && ".page" `isSuffixOf` path
69 = let encoded = makeRelative "/pages" $ dropExtension path
70 name = decodePageName encoded
77 loadPageInRepository :: Repository -> PageName -> Maybe RevNum -> IO (Maybe Page)
78 loadPageInRepository repos name rev
79 = do fs <- getRepositoryFS repos
81 Nothing -> getYoungestRev fs
84 $ do exists <- isFile path
87 -> return . Just =<< loadPage'
92 path = "pages" </> encodePageName name <.> "page"
95 loadPage' = do redirect <- getNodeProp path "rakka:redirect"
102 loadPageEntity :: Rev Page
104 = do props <- getNodePropList path
105 hist <- getNodeHistory True path
106 content <- getFileContentsLBS path
108 let pageRev = fst $ head hist
110 $ fromMaybe "text/x-rakka"
111 $ fmap chomp (lookup "svn:mime-type" props)
113 lastMod <- getRevisionProp "svn:date"
114 >>= return . fromJust . parseW3CDateTime . chomp . fromJust
118 , pageType = mimeType
119 , pageLanguage = fmap chomp (lookup "rakka:lang" props)
120 , pageFileName = fmap chomp (lookup "rakka:fileName" props)
121 , pageIsTheme = any ((== "rakka:isTheme") . fst) props
122 , pageIsFeed = any ((== "rakka:isFeed") . fst) props
123 , pageIsLocked = any ((== "rakka:isLocked") . fst) props
124 , pageIsBoring = any ((== "rakka:isBoring") . fst) props
125 , pageIsBinary = case mimeType of
127 -> any ((== "rakka:isBinary") . fst) props
130 , pageRevision = pageRev
131 , pageLastMod = zonedTimeToUTC lastMod
132 , pageSummary = lookup "rakka:summary" props
133 , pageOtherLang = fromMaybe M.empty
135 (M.fromList . fromJust . deserializeStringPairs)
136 (lookup "rakka:otherLang" props)
137 , pageContent = content
140 loadPageRedirect :: Rev Page
141 loadPageRedirect = fail "FIXME: loadPageRedirect: not implemented"