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.
This commit is contained in:
Joey Hess 2016-12-13 11:07:49 -04:00
parent f01b4cbf7c
commit d9490685fd
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
3 changed files with 31 additions and 19 deletions

View file

@ -1,6 +1,8 @@
git-annex (6.20161211) UNRELEASED; urgency=medium git-annex (6.20161211) UNRELEASED; urgency=medium
* Debian: Build webapp on armel. * Debian: Build webapp on armel.
* metadata --batch: Fix bug when conflicting metadata changes were
made in the same batch run.
-- Joey Hess <id@joeyh.name> Sun, 11 Dec 2016 21:29:51 -0400 -- Joey Hess <id@joeyh.name> Sun, 11 Dec 2016 21:29:51 -0400

View file

@ -20,6 +20,7 @@ import qualified Data.Text as T
import qualified Data.ByteString.Lazy.UTF8 as BU import qualified Data.ByteString.Lazy.UTF8 as BU
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
import Data.Aeson import Data.Aeson
import Control.Concurrent
cmd :: Command cmd :: Command
cmd = withGlobalOptions ([jsonOption] ++ annexedMatchingOptions) $ cmd = withGlobalOptions ([jsonOption] ++ annexedMatchingOptions) $
@ -65,23 +66,22 @@ optParser desc = MetaDataOptions
) )
seek :: MetaDataOptions -> CommandSeek seek :: MetaDataOptions -> CommandSeek
seek o = do seek o = case batchOption o of
now <- liftIO getPOSIXTime NoBatch -> do
case batchOption o of now <- liftIO getPOSIXTime
NoBatch -> do let seeker = case getSet o of
let seeker = case getSet o of Get _ -> withFilesInGit
Get _ -> withFilesInGit GetAll -> withFilesInGit
GetAll -> withFilesInGit Set _ -> withFilesInGitNonRecursive
Set _ -> withFilesInGitNonRecursive "Not recursively setting metadata. Use --force to do that."
"Not recursively setting metadata. Use --force to do that." withKeyOptions (keyOptions o) False
withKeyOptions (keyOptions o) False (startKeys now o)
(startKeys now o) (seeker $ whenAnnexed $ start now o)
(seeker $ whenAnnexed $ start now o) (forFiles o)
(forFiles o) Batch -> withMessageState $ \s -> case outputType s of
Batch -> withMessageState $ \s -> case outputType s of JSONOutput _ -> batchInput parseJSONInput $
JSONOutput _ -> batchInput parseJSONInput $ commandAction . startBatch
commandAction . startBatch now _ -> giveup "--batch is currently only supported in --json mode"
_ -> giveup "--batch is currently only supported in --json mode"
start :: POSIXTime -> MetaDataOptions -> FilePath -> Key -> CommandStart start :: POSIXTime -> MetaDataOptions -> FilePath -> Key -> CommandStart
start now o file k = startKeys now o k (mkActionItem afile) 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, Just f) -> Right (Left f, m)
(Nothing, Nothing) -> Left "JSON input is missing either file or key" (Nothing, Nothing) -> Left "JSON input is missing either file or key"
startBatch :: POSIXTime -> (Either FilePath Key, MetaData) -> CommandStart startBatch :: (Either FilePath Key, MetaData) -> CommandStart
startBatch now (i, (MetaData m)) = case i of startBatch (i, (MetaData m)) = case i of
Left f -> do Left f -> do
mk <- lookupFile f mk <- lookupFile f
case mk of case mk of
@ -169,6 +169,15 @@ startBatch now (i, (MetaData m)) = case i of
, keyOptions = Nothing , keyOptions = Nothing
, batchOption = NoBatch , 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 next $ perform now o k
mkModMeta (f, s) mkModMeta (f, s)
| S.null s = DelMeta f Nothing | S.null s = DelMeta f Nothing

View file

@ -82,3 +82,4 @@ I love the metadata functionality so much that I wrote [[tips/a_gui_for_metadata
Metadata driven views are awesome (but I don't like the entire folder hierarchy being appended to the filename). Metadata driven views are awesome (but I don't like the entire folder hierarchy being appended to the filename).
I haven't used the other commands much since I have not yet organized most of my stuff (and their naively copy-pasted backups), but I am glad I discovered git-annex before I began organizing. I haven't used the other commands much since I have not yet organized most of my stuff (and their naively copy-pasted backups), but I am glad I discovered git-annex before I began organizing.
> [[fixed|done]] --[[Joey]]