-- Copyright (C) 2003-2004 Jan Scheffczyk and David Roundy -- -- 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, 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; see the file COPYING. If not, write to -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. module Darcs.PopulationData ( Population(..), PopTree(..), Info(..), setPopState, notModified, setState, DirMark(..), getPopFrom ) where import Darcs.Patch.Info import Darcs.Utils ( withCurrentDirectory ) import System.Directory ( doesDirectoryExist, getDirectoryContents ) import qualified Data.ByteString.Char8 as BC import qualified Data.ByteString as B (ByteString) -- | the population of a darcs repository (simpler Slurpy) data Population = Pop { popState :: PatchInfo -- ^ the state when last modified , popTree :: PopTree -- ^ the directory listing } deriving (Show, Eq) setPopState :: PatchInfo -> Population -> Population setPopState i (Pop _ tr) = Pop i tr -- | directory listing data PopTree = PopDir !Info ![PopTree] | PopFile !Info deriving ( Ord, Eq ) -- | info of a directory member data DirMark = AddedFile | RemovedFile | MovedFile String | ModifiedFile | DullFile | AddedDir | RemovedDir | MovedDir !String | DullDir deriving ( Ord, Eq ) data Info = Info {nameI :: !B.ByteString, -- ^ name of the element modifiedByI :: !PatchInfo, -- ^ last patch modifying this element modifiedHowI :: !DirMark, -- ^ how was it modified createdByI :: !(Maybe PatchInfo), -- ^ this can be unknown when restored backwards! creationNameI :: !(Maybe B.ByteString) -- ^ the original name of the element } deriving ( Ord, Eq ) -- | was an Info record not modified? notModified :: Info -> Bool notModified i = (modifiedHowI i == DullFile) || (modifiedHowI i == DullDir) -- | set the modifier for an Info record setState :: Info -> PatchInfo -> Info setState i pinfo = i { modifiedByI = pinfo } instance Show PopTree where show s = showPop "" s showPop :: String -> PopTree -> String showPop indent (PopDir i fs) = indent ++ show i ++ "\n" ++ unlines (map (showPop (' ':indent)) fs) showPop indent (PopFile i) = indent ++ show i instance Show Info where show i = show (nameI i) ++ " " ++ show (modifiedHowI i) ++ " at state " ++ show (modifiedByI i) instance Show DirMark where show AddedFile = "File added" show RemovedFile = "File removed" show (MovedFile s) = "File moved to " ++ s show ModifiedFile = "File modified" show DullFile = "File old" show AddedDir = "Dir added" show RemovedDir = "Dir removed" show (MovedDir s) = "Dir moved from " ++ s show DullDir = "Dir old" -- | read the population from a given directory @dirname@ -- all folders and documents get the given time @t@ -- -- This needs to be here in order to avoid a circular dependency -- between Population and Pristine. getPopFrom :: FilePath -> PatchInfo -> IO Population getPopFrom the_directory pinfo = withCurrentDirectory the_directory $ do popT <- getPopFrom_helper "." return (Pop pinfo popT) where getPopFrom_helper :: FilePath -> IO PopTree getPopFrom_helper dirname = do isdir <- doesDirectoryExist dirname let n = BC.pack dirname if isdir then do fnames <- getDirectoryContents dirname sl <- withCurrentDirectory dirname (sequence $ map getPopFrom_helper $ filter not_hidden fnames) let i = Info {nameI = n, modifiedByI = pinfo, modifiedHowI = DullDir, createdByI = Just pinfo, creationNameI = Just n} return $ PopDir i sl else do let i = Info {nameI = n, modifiedByI = pinfo, modifiedHowI = DullFile, createdByI = Just pinfo, creationNameI = Just n} return $ PopFile i not_hidden :: FilePath -> Bool not_hidden ('.':_) = False not_hidden ('_':_) = False not_hidden _ = True