{-# LANGUAGE Rank2Types, TypeSynonymInstances, DeriveDataTypeable, FlexibleInstances #-} {- | Module : Data.FileStore.Types Copyright : Copyright (C) 2009 John MacFarlane License : BSD 3 Maintainer : John MacFarlane Stability : alpha Portability : GHC 6.10 required Type definitions for "Data.FileStore". -} module Data.FileStore.Types ( RevisionId , Resource(..) , Author(..) , Change(..) , Description , Revision(..) , Contents(..) , TimeRange(..) , MergeInfo(..) , FileStoreError(..) , SearchMatch(..) , SearchQuery(..) , defaultSearchQuery , UTCTime , FileStore (..) ) where import Data.ByteString.Lazy (ByteString) import Data.Typeable import Data.ByteString.Lazy.UTF8 (toString, fromString) import Data.Time (UTCTime) import Control.Exception (Exception) type RevisionId = String data Resource = FSFile FilePath | FSDirectory FilePath deriving (Show, Read, Eq, Typeable, Ord) data Author = Author { authorName :: String , authorEmail :: String } deriving (Show, Read, Eq, Typeable) data Change = Added FilePath | Deleted FilePath | Modified FilePath deriving (Show, Read, Eq, Typeable) type Description = String data Revision = Revision { revId :: RevisionId , revDateTime :: UTCTime , revAuthor :: Author , revDescription :: Description , revChanges :: [Change] } deriving (Show, Read, Eq, Typeable) class Contents a where fromByteString :: ByteString -> a toByteString :: a -> ByteString instance Contents ByteString where toByteString = id fromByteString = id instance Contents String where toByteString = fromString fromByteString = toString data TimeRange = TimeRange { timeFrom :: Maybe UTCTime -- ^ @Nothing@ means no lower bound , timeTo :: Maybe UTCTime -- ^ @Nothing@ means no upper bound } deriving (Show, Read, Eq, Typeable) data MergeInfo = MergeInfo { mergeRevision :: Revision -- ^ The revision w/ which changes were merged , mergeConflicts :: Bool -- ^ @True@ if there were merge conflicts , mergeText :: String -- ^ The merged text, w/ conflict markers } deriving (Show, Read, Eq, Typeable) data FileStoreError = RepositoryExists -- ^ Tried to initialize a repo that exists | ResourceExists -- ^ Tried to create a resource that exists | NotFound -- ^ Requested resource was not found | IllegalResourceName -- ^ The specified resource name is illegal | Unchanged -- ^ The resource was not modified, -- because the contents were unchanged | UnsupportedOperation | NoMaxCount -- ^ The darcs version used does not support -- --max-count | UnknownError String deriving (Read, Eq, Typeable) instance Show FileStoreError where show RepositoryExists = "RepositoryExists" show ResourceExists = "ResourceExists" show NotFound = "NotFound" show IllegalResourceName = "IllegalResourceName" show Unchanged = "Unchanged" show UnsupportedOperation = "UnsupportedOperation" show NoMaxCount = "NoMaxCount:\n" ++ "filestore was compiled with the maxcount flag, but your version of\n" ++ "darcs does not support the --max-count option. You should either\n" ++ "upgrade to darcs >= 2.3.0 (recommended) or compile filestore without\n" ++ "the maxcount flag (cabal install filestore -f-maxcount)." show (UnknownError s) = "UnknownError: " ++ s instance Exception FileStoreError data SearchQuery = SearchQuery { queryPatterns :: [String] -- ^ Patterns to match , queryWholeWords :: Bool -- ^ Match patterns only with whole words? , queryMatchAll :: Bool -- ^ Return matches only from files in which -- all patterns match? , queryIgnoreCase :: Bool -- ^ Make matches case-insensitive? } deriving (Show, Read, Eq, Typeable) defaultSearchQuery :: SearchQuery defaultSearchQuery = SearchQuery { queryPatterns = [] , queryWholeWords = True , queryMatchAll = True , queryIgnoreCase = True } data SearchMatch = SearchMatch { matchResourceName :: FilePath , matchLineNumber :: Integer , matchLine :: String } deriving (Show, Read, Eq, Typeable) -- | A versioning filestore, which can be implemented using the -- file system, a database, or revision-control software. data FileStore = FileStore { -- | Initialize a new filestore. initialize :: IO () -- | Save contents in the filestore. , save :: Contents a => FilePath -- Resource to save. -> Author -- Author of change. -> Description -- Description of change. -> a -- New contents of resource. -> IO () -- | Retrieve the contents of the named resource. , retrieve :: Contents a => FilePath -- Resource to retrieve. -> Maybe RevisionId -- @Just@ a particular revision ID, -- or @Nothing@ for latest -> IO a -- | Delete a named resource, providing author and log message. , delete :: FilePath -- Resource to delete. -> Author -- Author of change. -> Description -- Description of change. -> IO () -- | Rename a resource, providing author and log message. , rename :: FilePath -- Resource original name. -> FilePath -- Resource new name. -> Author -- Author of change. -> Description -- Description of change. -> IO () -- | Get history for a list of named resources in a (possibly openended) -- time range. If the list is empty, history for all resources will -- be returned. If the TimeRange is 2 Nothings, history for all dates will be returned. , history :: [FilePath] -- List of resources to get history for -- or @[]@ for all. -> TimeRange -- Time range in which to get history. -> Maybe Int -- Maybe max number of entries. -> IO [Revision] -- | Return the revision ID of the latest change for a resource. -- Raises 'NotFound' if the resource is not found. , latest :: FilePath -- Resource to get revision ID for. -> IO RevisionId -- | Return information about a revision, given the ID. -- Raises 'NotFound' if there is no such revision. , revision :: RevisionId -- Revision ID to get information for. -> IO Revision -- | Return a list of resources in the filestore. , index :: IO [FilePath] -- | Return a list of resources in a directory of the filestore. , directory :: FilePath -- Directory to list (empty for root) -> IO [Resource] -- | @True@ if the revision IDs match, in the sense that the -- can be treated as specifying the same revision. , idsMatch :: RevisionId -> RevisionId -> Bool -- | Search the filestore for patterns. , search :: SearchQuery -> IO [SearchMatch] }