git-annex/Database/Init.hs
Joey Hess 4cfe17a9e8
use a subdirectory of annex.dbdir
This allows annex.dbdir to be set globally or always set to the same
value when needed. Each repository uses a subdirectory of it.

Sponsored-by: Dartmouth College's Datalad project
2022-08-12 13:18:15 -04:00

65 lines
2.1 KiB
Haskell

{- Persistent sqlite database initialization
-
- Copyright 2015-2020 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
{-# LANGUAGE OverloadedStrings #-}
module Database.Init where
import Annex.Common
import qualified Annex
import Annex.Perms
import Utility.FileMode
import Utility.Directory.Create
import qualified Utility.RawFilePath as R
import Database.Persist.Sqlite
import Lens.Micro
import qualified Data.Text as T
import qualified System.FilePath.ByteString as P
{- Ensures that the database is freshly initialized. Deletes any
- existing database. Pass the migration action for the database.
-
- The permissions of the database are set based on the
- core.sharedRepository setting. Setting these permissions on the main db
- file causes Sqlite to always use the same permissions for additional
- files it writes later on
-}
initDb :: P.RawFilePath -> SqlPersistM () -> Annex ()
initDb db migration = do
let dbdir = P.takeDirectory db
let tmpdbdir = dbdir <> ".tmp"
let tmpdb = tmpdbdir P.</> "db"
let tdb = T.pack (fromRawFilePath tmpdb)
gc <- Annex.getGitConfig
top <- parentDir <$> fromRepo gitAnnexDir
let tops = case annexDbDir gc of
Just topdbdir -> [top, parentDir (parentDir topdbdir)]
Nothing -> [top]
liftIO $ do
createDirectoryUnder tops tmpdbdir
runSqliteInfo (enableWAL tdb) migration
setAnnexDirPerm tmpdbdir
-- Work around sqlite bug that prevents it from honoring
-- less restrictive umasks.
liftIO $ R.setFileMode tmpdb =<< defaultFileMode
setAnnexFilePerm tmpdb
liftIO $ do
void $ tryIO $ removeDirectoryRecursive (fromRawFilePath dbdir)
R.rename tmpdbdir dbdir
{- Make sure that the database uses WAL mode, to prevent readers
- from blocking writers, and prevent a writer from blocking readers.
-
- This is the default in recent persistent-sqlite versions, but
- force it on just in case.
-
- Note that once WAL mode is enabled, it will persist whenever the
- database is opened. -}
enableWAL :: T.Text -> SqliteConnectionInfo
enableWAL db = over walEnabled (const True) $
mkSqliteConnectionInfo db