git-annex/Backend.hs

101 lines
3 KiB
Haskell
Raw Normal View History

2010-10-10 17:47:04 +00:00
{- git-annex key/value storage backends
-
- git-annex uses a key/value abstraction layer to allow files contents to be
- stored in different ways. In theory, any key/value storage system could be
- used to store the file contents, and git-annex would then retrieve them
- as needed and put them in `.git/annex/`.
-
- When a file is annexed, a key is generated from its content and/or metadata.
- This key can later be used to retrieve the file's content (its value). This
- key generation must be stable for a given file content, name, and size.
-
- Multiple pluggable backends are supported, and more than one can be used
- to store different files' contents in a given repository.
- -}
2010-10-11 21:52:46 +00:00
module Backend (
2010-10-14 18:14:19 +00:00
storeFileKey,
retrieveKeyFile,
2010-10-14 21:37:20 +00:00
removeKey,
hasKey,
2010-10-13 07:20:05 +00:00
lookupFile
2010-10-11 21:52:46 +00:00
) where
2010-10-10 17:47:04 +00:00
2010-10-14 01:28:47 +00:00
import Control.Monad.State
2010-10-13 07:20:05 +00:00
import Control.Exception
2010-10-10 17:47:04 +00:00
import System.Directory
import System.FilePath
2010-10-12 20:39:10 +00:00
import Data.String.Utils
import System.Posix.Files
import BackendList
import Locations
2010-10-14 06:36:41 +00:00
import qualified GitRepo as Git
2010-10-14 07:18:11 +00:00
import qualified Annex
2010-10-10 19:04:18 +00:00
import Utility
2010-10-14 07:18:11 +00:00
import Types
2010-10-14 18:14:19 +00:00
import qualified BackendTypes as B
2010-10-14 19:58:53 +00:00
import BackendList
{- List of backends in the order to try them when storing a new key. -}
backendList :: Annex [Backend]
backendList = do
l <- Annex.backends
if (0 < length l)
then return l
else do
g <- Annex.gitRepo
let l = parseBackendList $ Git.configGet g "annex.backends" ""
Annex.backendsChange l
return l
2010-10-10 19:04:18 +00:00
2010-10-13 00:04:36 +00:00
{- Attempts to store a file in one of the backends. -}
2010-10-14 18:14:19 +00:00
storeFileKey :: FilePath -> Annex (Maybe (Key, Backend))
storeFileKey file = do
2010-10-14 07:18:11 +00:00
g <- Annex.gitRepo
2010-10-14 06:36:41 +00:00
let relfile = Git.relative g file
2010-10-14 20:13:43 +00:00
b <- backendList
2010-10-14 18:14:19 +00:00
storeFileKey' b file relfile
storeFileKey' [] _ _ = return Nothing
storeFileKey' (b:bs) file relfile = do
try <- (B.getKey b) relfile
2010-10-10 19:04:18 +00:00
case (try) of
2010-10-10 19:21:17 +00:00
Nothing -> nextbackend
2010-10-10 19:04:18 +00:00
Just key -> do
2010-10-14 18:14:19 +00:00
stored <- (B.storeFileKey b) file key
2010-10-10 19:21:17 +00:00
if (not stored)
then nextbackend
else do
2010-10-13 00:04:36 +00:00
return $ Just (key, b)
2010-10-10 19:21:17 +00:00
where
2010-10-14 18:14:19 +00:00
nextbackend = storeFileKey' bs file relfile
2010-10-10 19:04:18 +00:00
{- Attempts to retrieve an key from one of the backends, saving it to
2010-10-10 19:04:18 +00:00
- a specified location. -}
2010-10-14 18:14:19 +00:00
retrieveKeyFile :: Backend -> Key -> FilePath -> Annex Bool
retrieveKeyFile backend key dest = (B.retrieveKeyFile backend) key dest
2010-10-10 17:47:04 +00:00
2010-10-14 18:14:19 +00:00
{- Removes a key from a backend. -}
removeKey :: Backend -> Key -> Annex Bool
removeKey backend key = (B.removeKey backend) key
2010-10-12 20:39:10 +00:00
2010-10-15 00:05:04 +00:00
{- Checks if a backend has its key. -}
2010-10-14 21:37:20 +00:00
hasKey :: Key -> Annex Bool
2010-10-15 00:05:04 +00:00
hasKey key = (B.hasKey (lookupBackendName $ backendName key)) key
2010-10-14 21:37:20 +00:00
2010-10-13 07:20:05 +00:00
{- Looks up the key and backend corresponding to an annexed file,
- by examining what the file symlinks to. -}
2010-10-13 07:20:05 +00:00
lookupFile :: FilePath -> IO (Maybe (Key, Backend))
lookupFile file = do
result <- try (lookup)::IO (Either SomeException (Maybe (Key, Backend)))
case (result) of
Left err -> return Nothing
Right succ -> return succ
where
lookup = do
l <- readSymbolicLink file
2010-10-15 00:05:04 +00:00
return $ Just $ pair $ takeFileName l
pair file = (k, b)
where
k = fileKey file
b = lookupBackendName $ backendName k