summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Annex/Locations.hs10
-rw-r--r--Command/Export.hs17
-rw-r--r--Database/Export.hs85
-rw-r--r--git-annex.cabal1
4 files changed, 107 insertions, 6 deletions
diff --git a/Annex/Locations.hs b/Annex/Locations.hs
index 47768b9c1..a5de2e4ff 100644
--- a/Annex/Locations.hs
+++ b/Annex/Locations.hs
@@ -36,6 +36,7 @@ module Annex.Locations (
gitAnnexFsckDbDir,
gitAnnexFsckDbLock,
gitAnnexFsckResultsLog,
+ gitAnnexExportDbDir,
gitAnnexScheduleState,
gitAnnexTransferDir,
gitAnnexCredsDir,
@@ -290,6 +291,15 @@ gitAnnexFsckDbLock u r = gitAnnexFsckDir u r </> "fsck.lck"
gitAnnexFsckResultsLog :: UUID -> Git.Repo -> FilePath
gitAnnexFsckResultsLog u r = gitAnnexDir r </> "fsckresults" </> fromUUID u
+{- .git/annex/export/uuid/ is used to store information about
+ - exports to special remotes. -}
+gitAnnexExportDir :: UUID -> Git.Repo -> FilePath
+gitAnnexExportDir u r = gitAnnexDir r </> "export" </> fromUUID u
+
+{- Directory containing database used to record export info. -}
+gitAnnexExportDbDir :: UUID -> Git.Repo -> FilePath
+gitAnnexExportDbDir u r = gitAnnexExportDir u r </> "db"
+
{- .git/annex/schedulestate is used to store information about when
- scheduled jobs were last run. -}
gitAnnexScheduleState :: Git.Repo -> FilePath
diff --git a/Command/Export.hs b/Command/Export.hs
index 03d549cbf..1f293025b 100644
--- a/Command/Export.hs
+++ b/Command/Export.hs
@@ -21,6 +21,7 @@ import Annex.Content
import Annex.CatFile
import Logs.Location
import Logs.Export
+import Database.Export
import Messages.Progress
import Utility.Tmp
@@ -81,6 +82,8 @@ seek o = do
when (length old > 1) $
warning "Export conflict detected. Different trees have been exported to the same special remote. Resolving.."
+ db <- openDb (uuid r)
+
-- First, diff the old and new trees and delete all changed
-- files in the export. Every file that remains in the export will
-- have the content from the new treeish.
@@ -89,7 +92,7 @@ seek o = do
forM_ old $ \oldtreesha -> do
(diff, cleanup) <- inRepo $
Git.DiffTree.diffTreeRecursive oldtreesha new
- seekActions $ pure $ map (startUnexport r) diff
+ seekActions $ pure $ map (startUnexport r db) diff
void $ liftIO cleanup
-- Waiting until now to record the export guarantees that,
@@ -102,12 +105,13 @@ seek o = do
-- Export everything that is not yet exported.
(l, cleanup') <- inRepo $ Git.LsTree.lsTree new
- seekActions $ pure $ map (startExport r) l
+ seekActions $ pure $ map (startExport r db) l
void $ liftIO cleanup'
-startExport :: Remote -> Git.LsTree.TreeItem -> CommandStart
-startExport r ti = do
+startExport :: Remote -> ExportHandle -> Git.LsTree.TreeItem -> CommandStart
+startExport r db ti = do
ek <- exportKey (Git.LsTree.sha ti)
+ liftIO $ addExportLocation db (asKey ek) loc
stopUnless (notElem (uuid r) <$> loggedLocations (asKey ek)) $ do
showStart "export" f
next $ performExport r ek (Git.LsTree.sha ti) loc
@@ -144,11 +148,12 @@ cleanupExport r ek = do
logChange (asKey ek) (uuid r) InfoPresent
return True
-startUnexport :: Remote -> Git.DiffTree.DiffTreeItem -> CommandStart
-startUnexport r diff
+startUnexport :: Remote -> ExportHandle -> Git.DiffTree.DiffTreeItem -> CommandStart
+startUnexport r db diff
| Git.DiffTree.srcsha diff /= nullSha = do
showStart "unexport" f
oldk <- exportKey (Git.DiffTree.srcsha diff)
+ liftIO $ removeExportLocation db (asKey oldk) loc
next $ performUnexport r oldk loc
| otherwise = stop
where
diff --git a/Database/Export.hs b/Database/Export.hs
new file mode 100644
index 000000000..bc79af29f
--- /dev/null
+++ b/Database/Export.hs
@@ -0,0 +1,85 @@
+{- Sqlite database used for exports to special remotes.
+ -
+ - Copyright 2017 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.Export (
+ ExportHandle,
+ openDb,
+ closeDb,
+ addExportLocation,
+ removeExportLocation,
+ getExportLocation,
+ ExportedId,
+) where
+
+import Database.Types
+import qualified Database.Queue as H
+import Database.Init
+import Annex.Locations
+import Annex.Common hiding (delete)
+import Types.Remote (ExportLocation(..))
+
+import Database.Persist.TH
+import Database.Esqueleto hiding (Key)
+
+data ExportHandle = ExportHandle H.DbQueue
+
+share [mkPersist sqlSettings, mkMigrate "migrateExport"] [persistLowerCase|
+Exported
+ key IKey
+ file SFilePath
+ KeyFileIndex key file
+ UniqueKey key
+|]
+
+{- Opens the database, creating it if it doesn't exist yet. -}
+openDb :: UUID -> Annex ExportHandle
+openDb u = do
+ dbdir <- fromRepo (gitAnnexExportDbDir u)
+ let db = dbdir </> "db"
+ unlessM (liftIO $ doesFileExist db) $ do
+ initDb db $ void $
+ runMigrationSilent migrateExport
+ h <- liftIO $ H.openDbQueue db "exported"
+ return $ ExportHandle h
+
+closeDb :: ExportHandle -> Annex ()
+closeDb (ExportHandle h) = liftIO $ H.closeDbQueue h
+
+queueDb :: ExportHandle -> SqlPersistM () -> IO ()
+queueDb (ExportHandle h) = H.queueDb h checkcommit
+ where
+ -- commit queue after 1000 changes
+ checkcommit sz _lastcommittime
+ | sz > 1000 = return True
+ | otherwise = return False
+
+addExportLocation :: ExportHandle -> Key -> ExportLocation -> IO ()
+addExportLocation h k (ExportLocation f) = queueDb h $
+ void $ insertUnique $ Exported (toIKey k) (toSFilePath f)
+
+removeExportLocation :: ExportHandle -> Key -> ExportLocation -> IO ()
+removeExportLocation h k (ExportLocation f) = queueDb h $
+ delete $ from $ \r -> do
+ where_ (r ^. ExportedKey ==. val ik &&. r ^. ExportedFile ==. val ef)
+ where
+ ik = toIKey k
+ ef = toSFilePath f
+
+{- Doesn't know about recently queued changes. -}
+getExportLocation :: ExportHandle -> Key -> IO [ExportLocation]
+getExportLocation (ExportHandle h) k = H.queryDbQueue h $ do
+ l <- select $ from $ \r -> do
+ where_ (r ^. ExportedKey ==. val ik)
+ return (r ^. ExportedFile)
+ return $ map (ExportLocation . fromSFilePath . unValue) l
+ where
+ ik = toIKey k
diff --git a/git-annex.cabal b/git-annex.cabal
index 178531de0..af31207bd 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -787,6 +787,7 @@ Executable git-annex
Config.GitConfig
Creds
Crypto
+ Database.Export
Database.Fsck
Database.Handle
Database.Init