Graceful handling of undone corrections
This commit is contained in:
parent
f6e7b3fe25
commit
d01404047f
@ -267,45 +267,60 @@ sinkSubmission sheetId userId mExists = do
|
|||||||
when alreadySeen . throwM $ DuplicateFileTitle fileTitle
|
when alreadySeen . throwM $ DuplicateFileTitle fileTitle
|
||||||
tell $ mempty{ sinkFilenames = Set.singleton fileTitle }
|
tell $ mempty{ sinkFilenames = Set.singleton fileTitle }
|
||||||
|
|
||||||
collidingFiles <- lift . E.select . E.from $ \(sf `E.InnerJoin` f) -> do
|
otherVersions <- lift . E.select . E.from $ \(sf `E.InnerJoin` f) -> do
|
||||||
E.on $ sf E.^. SubmissionFileFileId E.==. f E.^. FileId
|
E.on $ sf E.^. SubmissionFileFileId E.==. f E.^. FileId
|
||||||
E.where_ $ sf E.^. SubmissionFileSubmissionId E.==. E.val submissionId
|
E.where_ $ sf E.^. SubmissionFileSubmissionId E.==. E.val submissionId
|
||||||
E.where_ $ sf E.^. SubmissionFileIsUpdate E.==. E.val isUpdate
|
-- E.where_ $ sf E.^. SubmissionFileIsUpdate E.==. E.val isUpdate
|
||||||
E.where_ $ f E.^. FileTitle E.==. E.val fileTitle -- 'Zip.hs' normalises filenames already, so this should work
|
E.where_ $ f E.^. FileTitle E.==. E.val fileTitle -- 'Zip.hs' normalises filenames already, so this should work
|
||||||
return (f, sf)
|
return (f, sf)
|
||||||
|
|
||||||
let anyChanges
|
let collidingFiles = [ t | t@(_, Entity _ sf) <- otherVersions
|
||||||
| not (null collidingFiles) = any (/= file) [ f | (Entity _ f, _) <- collidingFiles ]
|
, submissionFileIsUpdate sf == isUpdate
|
||||||
| otherwise = True
|
]
|
||||||
undoneDeletion = any submissionFileIsDeletion [ sf | (_, Entity _ sf) <- collidingFiles ]
|
underlyingFiles = [ t | t@(_, Entity _ sf) <- otherVersions
|
||||||
-- The Eq Instance for File compares modification time exactly even
|
, submissionFileIsUpdate sf == False
|
||||||
-- though zip archives have very limited accuracy and range regarding
|
]
|
||||||
-- timestamps.
|
anyChanges
|
||||||
-- We thus expect to replace files a little more often than is actually
|
| not (null collidingFiles) = any (/~ file) [ f | (Entity _ f, _) <- collidingFiles ]
|
||||||
-- necessary.
|
| otherwise = True
|
||||||
-- This was done on the premise that changes in file modification time
|
matchesUnderlying
|
||||||
-- break file identity under upload and re-download.
|
| not (null underlyingFiles) = all (~~ file) [ f | (Entity _ f, Entity _ sf) <- underlyingFiles ]
|
||||||
--
|
| otherwise = False
|
||||||
-- We could check whether the new version of the file matches the
|
undoneDeletion = any submissionFileIsDeletion [ sf | (_, Entity _ sf) <- collidingFiles
|
||||||
-- version of the file for which 'isUpdate' is different from this
|
]
|
||||||
-- one's, and, if so, simply delete the version for which 'isUpdate' is
|
|
||||||
-- 'True', reverting the correction.
|
a /~ b = not $ a ~~ b
|
||||||
--
|
|
||||||
-- This idea was discarded since modification times make this difficult
|
(~~) :: File -> File -> Bool
|
||||||
-- to implement properly – should we equate file versions that differ in
|
(~~) = (==)
|
||||||
-- modification time?
|
-- The Eq Instance for File compares modification time exactly even
|
||||||
|
-- though zip archives have very limited accuracy and range regarding
|
||||||
|
-- timestamps.
|
||||||
|
-- We thus expect to replace files a little more often than is actually
|
||||||
|
-- necessary.
|
||||||
|
-- This was done on the premise that changes in file modification time
|
||||||
|
-- break file identity under upload and re-download.
|
||||||
|
--
|
||||||
|
-- Similarly the check whether the new version matches the underlying
|
||||||
|
-- file is arguably too agressive, marking files, differing only in
|
||||||
|
-- modification time, as modified.
|
||||||
|
|
||||||
when anyChanges $ do
|
when anyChanges $ do
|
||||||
touchSubmission
|
touchSubmission
|
||||||
when (not $ null collidingFiles) $
|
when (not $ null collidingFiles) $
|
||||||
lift $ deleteCascadeWhere [ FileId <-. [ fId | (Entity fId _, _) <- collidingFiles ] ]
|
lift $ deleteCascadeWhere [ FileId <-. [ fId | (Entity fId _, _) <- collidingFiles ] ]
|
||||||
fileId <- lift $ insert file
|
lift $ case () of
|
||||||
lift . insert_ $ SubmissionFile
|
_ | matchesUnderlying
|
||||||
{ submissionFileSubmissionId = submissionId
|
, isUpdate
|
||||||
, submissionFileFileId = fileId
|
-> return ()
|
||||||
, submissionFileIsUpdate = isUpdate
|
_ -> do
|
||||||
, submissionFileIsDeletion = False
|
fileId <- insert file
|
||||||
}
|
insert_ $ SubmissionFile
|
||||||
|
{ submissionFileSubmissionId = submissionId
|
||||||
|
, submissionFileFileId = fileId
|
||||||
|
, submissionFileIsUpdate = isUpdate
|
||||||
|
, submissionFileIsDeletion = False
|
||||||
|
}
|
||||||
when undoneDeletion $ do
|
when undoneDeletion $ do
|
||||||
touchSubmission
|
touchSubmission
|
||||||
lift $ deleteWhere [ SubmissionFileId <-. [ sfId | (_, Entity sfId sf) <- collidingFiles, submissionFileIsDeletion sf ] ]
|
lift $ deleteWhere [ SubmissionFileId <-. [ sfId | (_, Entity sfId sf) <- collidingFiles, submissionFileIsDeletion sf ] ]
|
||||||
|
|||||||
Reference in New Issue
Block a user