1 -- Copyright (C) 2003-2004 Jan Scheffczyk and David Roundy 2 -- 3 -- This program is free software; you can redistribute it and/or modify 4 -- it under the terms of the GNU General Public License as published by 5 -- the Free Software Foundation; either version 2, or (at your option) 6 -- any later version. 7 -- 8 -- This program is distributed in the hope that it will be useful, 9 -- but WITHOUT ANY WARRANTY; without even the implied warranty of 10 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 -- GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License 14 -- along with this program; see the file COPYING. If not, write to 15 -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 16 -- Boston, MA 02110-1301, USA. 17 18 module Darcs.PopulationData ( Population(..), PopTree(..), Info(..), 19 setPopState, notModified, setState, 20 DirMark(..), getPopFrom 21 ) where 22 import Darcs.Patch.Info 23 import Darcs.Utils ( withCurrentDirectory ) 24 import System.Directory ( doesDirectoryExist, getDirectoryContents ) 25 import qualified Data.ByteString.Char8 as BC 26 import qualified Data.ByteString as B (ByteString) 27 28 -- | the population of a darcs repository (simpler Slurpy) 29 data Population = Pop { popState :: PatchInfo -- ^ the state when last modified 30 , popTree :: PopTree -- ^ the directory listing 31 } 32 deriving (Show, Eq) 33 34 setPopState :: PatchInfo -> Population -> Population 35 setPopState i (Pop _ tr) = Pop i tr 36 37 -- | directory listing 38 data PopTree = PopDir !Info ![PopTree] 39 | PopFile !Info 40 deriving ( Ord, Eq ) 41 42 -- | info of a directory member 43 data DirMark = AddedFile | RemovedFile | MovedFile String 44 | ModifiedFile | DullFile 45 | AddedDir | RemovedDir | MovedDir !String | DullDir 46 deriving ( Ord, Eq ) 47 data Info = Info {nameI :: !B.ByteString, -- ^ name of the element 48 modifiedByI :: !PatchInfo, -- ^ last patch modifying this element 49 modifiedHowI :: !DirMark, -- ^ how was it modified 50 createdByI :: !(Maybe PatchInfo), -- ^ this can be unknown when restored backwards! 51 creationNameI :: !(Maybe B.ByteString) -- ^ the original name of the element 52 } 53 deriving ( Ord, Eq ) 54 55 -- | was an Info record not modified? 56 notModified :: Info -> Bool 57 notModified i = (modifiedHowI i == DullFile) || (modifiedHowI i == DullDir) 58 59 -- | set the modifier for an Info record 60 setState :: Info -> PatchInfo -> Info 61 setState i pinfo = i { modifiedByI = pinfo } 62 63 instance Show PopTree where 64 show s = showPop "" s 65 66 showPop :: String -> PopTree -> String 67 showPop indent (PopDir i fs) 68 = indent ++ show i ++ "\n" ++ 69 unlines (map (showPop (' ':indent)) fs) 70 showPop indent (PopFile i) 71 = indent ++ show i 72 73 instance Show Info where 74 show i = show (nameI i) ++ " " ++ show (modifiedHowI i) ++ 75 " at state " ++ show (modifiedByI i) 76 77 instance Show DirMark where 78 show AddedFile = "File added" 79 show RemovedFile = "File removed" 80 show (MovedFile s) = "File moved to " ++ s 81 show ModifiedFile = "File modified" 82 show DullFile = "File old" 83 show AddedDir = "Dir added" 84 show RemovedDir = "Dir removed" 85 show (MovedDir s) = "Dir moved from " ++ s 86 show DullDir = "Dir old" 87 88 -- | read the population from a given directory @dirname@ 89 -- all folders and documents get the given time @t@ 90 -- 91 -- This needs to be here in order to avoid a circular dependency 92 -- between Population and Pristine. 93 getPopFrom :: FilePath -> PatchInfo -> IO Population 94 getPopFrom the_directory pinfo = 95 withCurrentDirectory the_directory $ 96 do popT <- getPopFrom_helper "." 97 return (Pop pinfo popT) 98 where getPopFrom_helper :: FilePath -> IO PopTree 99 getPopFrom_helper dirname = do 100 isdir <- doesDirectoryExist dirname 101 let n = BC.pack dirname 102 if isdir 103 then do 104 fnames <- getDirectoryContents dirname 105 sl <- withCurrentDirectory dirname 106 (sequence $ map getPopFrom_helper $ filter not_hidden fnames) 107 let i = Info {nameI = n, 108 modifiedByI = pinfo, 109 modifiedHowI = DullDir, 110 createdByI = Just pinfo, 111 creationNameI = Just n} 112 return $ PopDir i sl 113 else do let i = Info {nameI = n, 114 modifiedByI = pinfo, 115 modifiedHowI = DullFile, 116 createdByI = Just pinfo, 117 creationNameI = Just n} 118 return $ PopFile i 119 120 not_hidden :: FilePath -> Bool 121 not_hidden ('.':_) = False 122 not_hidden ('_':_) = False 123 not_hidden _ = True