associated files database
This commit is contained in:
parent
63c466449f
commit
a6e5ee0d0e
3 changed files with 105 additions and 1 deletions
94
Database/AssociatedFiles.hs
Normal file
94
Database/AssociatedFiles.hs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
{- Sqlite database used for tracking a key's associated files.
|
||||||
|
-
|
||||||
|
- Copyright 2015 Joey Hess <id@joeyh.name>
|
||||||
|
-:
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
{-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings, GADTs, FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses, GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
|
||||||
|
module Database.AssociatedFiles (
|
||||||
|
DbHandle,
|
||||||
|
openDb,
|
||||||
|
closeDb,
|
||||||
|
addDb,
|
||||||
|
getDb,
|
||||||
|
removeDb,
|
||||||
|
AssociatedId,
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Database.Types
|
||||||
|
import qualified Database.Handle as H
|
||||||
|
import Locations
|
||||||
|
import Common hiding (delete)
|
||||||
|
import Annex
|
||||||
|
import Types.Key
|
||||||
|
import Annex.Perms
|
||||||
|
import Annex.LockFile
|
||||||
|
import Messages
|
||||||
|
|
||||||
|
import Database.Persist.TH
|
||||||
|
import Database.Esqueleto hiding (Key)
|
||||||
|
|
||||||
|
newtype DbHandle = DbHandle H.DbHandle
|
||||||
|
|
||||||
|
share [mkPersist sqlSettings, mkMigrate "migrateAssociated"] [persistLowerCase|
|
||||||
|
Associated
|
||||||
|
key SKey
|
||||||
|
file FilePath
|
||||||
|
KeyFileIndex key file
|
||||||
|
|]
|
||||||
|
|
||||||
|
{- Opens the database, creating it if it doesn't exist yet. -}
|
||||||
|
openDb :: Annex DbHandle
|
||||||
|
openDb = withExclusiveLock gitAnnexAssociatedFilesDbLock $ do
|
||||||
|
dbdir <- fromRepo gitAnnexAssociatedFilesDb
|
||||||
|
let db = dbdir </> "db"
|
||||||
|
unlessM (liftIO $ doesFileExist db) $ do
|
||||||
|
liftIO $ do
|
||||||
|
createDirectoryIfMissing True dbdir
|
||||||
|
H.initDb db $ void $
|
||||||
|
runMigrationSilent migrateAssociated
|
||||||
|
setAnnexDirPerm dbdir
|
||||||
|
setAnnexFilePerm db
|
||||||
|
h <- liftIO $ H.openDb db "associated"
|
||||||
|
|
||||||
|
-- work around https://github.com/yesodweb/persistent/issues/474
|
||||||
|
liftIO setConsoleEncoding
|
||||||
|
|
||||||
|
return $ DbHandle h
|
||||||
|
|
||||||
|
closeDb :: DbHandle -> IO ()
|
||||||
|
closeDb (DbHandle h) = H.closeDb h
|
||||||
|
|
||||||
|
addDb :: DbHandle -> Key -> FilePath -> IO ()
|
||||||
|
addDb (DbHandle h) k f = H.queueDb h (\_ _ -> pure True) $ do
|
||||||
|
-- If the same file was associated with a different key before,
|
||||||
|
-- remove that.
|
||||||
|
delete $ from $ \r -> do
|
||||||
|
where_ (r ^. AssociatedFile ==. val f &&. r ^. AssociatedKey ==. val sk)
|
||||||
|
void $ insertUnique $ Associated sk f
|
||||||
|
where
|
||||||
|
sk = toSKey k
|
||||||
|
|
||||||
|
{- Note that the files returned used to be associated with the key, but
|
||||||
|
- some of them may not be any longer. -}
|
||||||
|
getDb :: DbHandle -> Key -> IO [FilePath]
|
||||||
|
getDb (DbHandle h) = H.queryDb h . getDb' . toSKey
|
||||||
|
|
||||||
|
getDb' :: SKey -> SqlPersistM [FilePath]
|
||||||
|
getDb' sk = do
|
||||||
|
l <- select $ from $ \r -> do
|
||||||
|
where_ (r ^. AssociatedKey ==. val sk)
|
||||||
|
return (r ^. AssociatedFile)
|
||||||
|
return $ map unValue l
|
||||||
|
|
||||||
|
removeDb :: DbHandle -> Key -> FilePath -> IO ()
|
||||||
|
removeDb (DbHandle h) k f = H.queueDb h (\_ _ -> pure True) $
|
||||||
|
delete $ from $ \r -> do
|
||||||
|
where_ (r ^. AssociatedKey ==. val sk &&. r ^. AssociatedFile ==. val f)
|
||||||
|
where
|
||||||
|
sk = toSKey k
|
|
@ -59,7 +59,7 @@ newPass u = isJust <$> tryExclusiveLock (gitAnnexFsckDbLock u) go
|
||||||
go = liftIO . void . tryIO . removeDirectoryRecursive
|
go = liftIO . void . tryIO . removeDirectoryRecursive
|
||||||
=<< fromRepo (gitAnnexFsckDbDir u)
|
=<< fromRepo (gitAnnexFsckDbDir u)
|
||||||
|
|
||||||
{- Opens the database, creating it atomically if it doesn't exist yet. -}
|
{- Opens the database, creating it if it doesn't exist yet. -}
|
||||||
openDb :: UUID -> Annex FsckHandle
|
openDb :: UUID -> Annex FsckHandle
|
||||||
openDb u = do
|
openDb u = do
|
||||||
dbdir <- fromRepo (gitAnnexFsckDbDir u)
|
dbdir <- fromRepo (gitAnnexFsckDbDir u)
|
||||||
|
|
10
Locations.hs
10
Locations.hs
|
@ -29,6 +29,8 @@ module Locations (
|
||||||
gitAnnexBadDir,
|
gitAnnexBadDir,
|
||||||
gitAnnexBadLocation,
|
gitAnnexBadLocation,
|
||||||
gitAnnexUnusedLog,
|
gitAnnexUnusedLog,
|
||||||
|
gitAnnexAssociatedFilesDb,
|
||||||
|
gitAnnexAssociatedFilesDbLock,
|
||||||
gitAnnexFsckState,
|
gitAnnexFsckState,
|
||||||
gitAnnexFsckDbDir,
|
gitAnnexFsckDbDir,
|
||||||
gitAnnexFsckDbLock,
|
gitAnnexFsckDbLock,
|
||||||
|
@ -237,6 +239,14 @@ gitAnnexBadLocation key r = gitAnnexBadDir r </> keyFile key
|
||||||
gitAnnexUnusedLog :: FilePath -> Git.Repo -> FilePath
|
gitAnnexUnusedLog :: FilePath -> Git.Repo -> FilePath
|
||||||
gitAnnexUnusedLog prefix r = gitAnnexDir r </> (prefix ++ "unused")
|
gitAnnexUnusedLog prefix r = gitAnnexDir r </> (prefix ++ "unused")
|
||||||
|
|
||||||
|
{- .git/annex/map/ contains a database for the associated files map -}
|
||||||
|
gitAnnexAssociatedFilesDb :: Git.Repo -> FilePath
|
||||||
|
gitAnnexAssociatedFilesDb r = gitAnnexDir r </> "map"
|
||||||
|
|
||||||
|
{- Lock file for the associated files map database. -}
|
||||||
|
gitAnnexAssociatedFilesDbLock :: Git.Repo -> FilePath
|
||||||
|
gitAnnexAssociatedFilesDbLock r = gitAnnexAssociatedFilesDb r ++ "lck"
|
||||||
|
|
||||||
{- .git/annex/fsck/uuid/ is used to store information about incremental
|
{- .git/annex/fsck/uuid/ is used to store information about incremental
|
||||||
- fscks. -}
|
- fscks. -}
|
||||||
gitAnnexFsckDir :: UUID -> Git.Repo -> FilePath
|
gitAnnexFsckDir :: UUID -> Git.Repo -> FilePath
|
||||||
|
|
Loading…
Add table
Reference in a new issue