aboutsummaryrefslogtreecommitdiff
path: root/Command/MetaData.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2016-12-13 11:07:49 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2016-12-13 11:07:49 -0400
commitc254d141bec24c0cb2931247cac8d4c8bd4105be (patch)
tree3074da422e8eab7510dd0356385d67a71d4dd0bc /Command/MetaData.hs
parent1d359620940f5b8c2476c5a32ee9922b5d53bb4f (diff)
metadata --batch: Fix bug when conflicting metadata changes were made in the same batch run.
1 microsecond delay is ugly.. but, maintaining an queue of a list of timestamps and taking a new one from the queue each time around, or maintaining a timestamp counter, would probably be slower.
Diffstat (limited to 'Command/MetaData.hs')
-rw-r--r--Command/MetaData.hs47
1 files changed, 28 insertions, 19 deletions
diff --git a/Command/MetaData.hs b/Command/MetaData.hs
index 04d859e4c..ebb9d0f17 100644
--- a/Command/MetaData.hs
+++ b/Command/MetaData.hs
@@ -20,6 +20,7 @@ import qualified Data.Text as T
import qualified Data.ByteString.Lazy.UTF8 as BU
import Data.Time.Clock.POSIX
import Data.Aeson
+import Control.Concurrent
cmd :: Command
cmd = withGlobalOptions ([jsonOption] ++ annexedMatchingOptions) $
@@ -65,23 +66,22 @@ optParser desc = MetaDataOptions
)
seek :: MetaDataOptions -> CommandSeek
-seek o = do
- now <- liftIO getPOSIXTime
- case batchOption o of
- NoBatch -> do
- let seeker = case getSet o of
- Get _ -> withFilesInGit
- GetAll -> withFilesInGit
- Set _ -> withFilesInGitNonRecursive
- "Not recursively setting metadata. Use --force to do that."
- withKeyOptions (keyOptions o) False
- (startKeys now o)
- (seeker $ whenAnnexed $ start now o)
- (forFiles o)
- Batch -> withMessageState $ \s -> case outputType s of
- JSONOutput _ -> batchInput parseJSONInput $
- commandAction . startBatch now
- _ -> giveup "--batch is currently only supported in --json mode"
+seek o = case batchOption o of
+ NoBatch -> do
+ now <- liftIO getPOSIXTime
+ let seeker = case getSet o of
+ Get _ -> withFilesInGit
+ GetAll -> withFilesInGit
+ Set _ -> withFilesInGitNonRecursive
+ "Not recursively setting metadata. Use --force to do that."
+ withKeyOptions (keyOptions o) False
+ (startKeys now o)
+ (seeker $ whenAnnexed $ start now o)
+ (forFiles o)
+ Batch -> withMessageState $ \s -> case outputType s of
+ JSONOutput _ -> batchInput parseJSONInput $
+ commandAction . startBatch
+ _ -> giveup "--batch is currently only supported in --json mode"
start :: POSIXTime -> MetaDataOptions -> FilePath -> Key -> CommandStart
start now o file k = startKeys now o k (mkActionItem afile)
@@ -150,8 +150,8 @@ parseJSONInput i = do
(Nothing, Just f) -> Right (Left f, m)
(Nothing, Nothing) -> Left "JSON input is missing either file or key"
-startBatch :: POSIXTime -> (Either FilePath Key, MetaData) -> CommandStart
-startBatch now (i, (MetaData m)) = case i of
+startBatch :: (Either FilePath Key, MetaData) -> CommandStart
+startBatch (i, (MetaData m)) = case i of
Left f -> do
mk <- lookupFile f
case mk of
@@ -169,6 +169,15 @@ startBatch now (i, (MetaData m)) = case i of
, keyOptions = Nothing
, batchOption = NoBatch
}
+ now <- liftIO getPOSIXTime
+ -- It would be bad if two batch mode changes used exactly
+ -- the same timestamp, since the order of adds and removals
+ -- of the same metadata value would then be indeterminate.
+ -- To guarantee that never happens, delay 1 microsecond,
+ -- so the timestamp will always be different. This is
+ -- probably less expensive than cleaner methods,
+ -- such as taking from a list of increasing timestamps.
+ liftIO $ threadDelay 1
next $ perform now o k
mkModMeta (f, s)
| S.null s = DelMeta f Nothing