-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding 'MustExist' constructor to assert a file is assumed to exist #85
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feature! Some suggestions below
-- | Open a file: create it if necessary or throw an error if either: | ||
-- 1. It existed already while we were supposed to create it from scratch | ||
-- (when passed 'MustBeNew'). | ||
-- 2. It did not already exists when we expected to (when passed 'MustExist'). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's link to AllowExisting
instead, which already describes the intended semantics
-- | Open a file: create it if necessary or throw an error if either: | |
-- 1. It existed already while we were supposed to create it from scratch | |
-- (when passed 'MustBeNew'). | |
-- 2. It did not already exists when we expected to (when passed 'MustExist'). | |
-- | Open a file based on an 'AllowExisting'. |
caseAlreadyExist a = case ex of | ||
MustBeNew -> Left (FsExists fp) | ||
_ -> Right a | ||
|
||
caseDoesNotExist = case ex of | ||
MustExist -> Left (FsMissing fp (pathLast fp :| [])) | ||
_ -> Right mempty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preferably, list all constructors, so that we won't forget to update the cases if the AllowExisting
type changes in the future
let assumedExistance (WriteMode MustExist) = True | ||
assumedExistance (AppendMode MustExist) = True | ||
assumedExistance (ReadWriteMode MustExist) = True | ||
assumedExistance _ = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe name it fileShouldExist
?
-- ('FsResourceAlreadyExist') is thrown. | ||
| MustExist | ||
-- ^ The file must already exist. If it does not, an error | ||
-- ('FsResourceDoesNotExist') is thrown. | ||
deriving (Eq, Show) | ||
|
||
allowExisting :: OpenMode -> AllowExisting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder, should allowExisting ReadMode = MustExist
? That seems to be line with the semantics of hOpen
on Unix
at least.
Let's also take this opportunity to document the semantics of ReadMode
. Something like: if opening a file in read mode, then the file must exist or an exception is thrown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also add a TODO to test that this is the actual behaviour on both Windows and Unix. Hopefully this is already checked by the state machine tests, but it does not hurt to have some more targeted property tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there should probably also be an issue to properly document OpenMode
. I'll create that
createNew AllowExisting = oPEN_ALWAYS | ||
createNew MustBeNew = cREATE_NEW | ||
createNew MustExist = oPEN_ALWAYS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be wrong: MustExist
and AllowExisting
get the same file flags
when (openMode == ReadMode || assumedExistance openMode) $ void $ | ||
checkFsTree $ FS.getFile fp (mockFiles fs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we make the change allowExisting ReadMode = MustExist
, then I think this check can go away completely. openFile
should then already throw the correct error
@@ -1055,6 +1055,7 @@ data Tag = | |||
-- > Get .. | |||
| TagPutSeekNegGet | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-- Open with MustExist, but the file does not exist. | ||
-- | ||
-- > DoesFileExist fp | ||
-- > h <- Open fp (AppendMode _) | ||
| TagAssumeExists |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A similar tag for opening a non-existent file in read mode would also be useful
@@ -1136,6 +1144,7 @@ tag = C.classify [ | |||
, tagPutSeekGet Set.empty Set.empty | |||
, tagPutSeekNegGet Set.empty Set.empty | |||
, tagExclusiveFail | |||
-- , tagAssumeExistsFail -- Set.empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be updated
{- | ||
tagClosedTwice closed = successful $ \ev _suc -> | ||
case eventMockCmd ev of | ||
Close (Handle h _) | Set.member h closed -> Left TagClosedTwice | ||
Close (Handle h _) -> Right $ tagClosedTwice $ Set.insert h closed | ||
_otherwise -> Right $ tagClosedTwice closed | ||
(DoesFileExist _, Bool False) -> Left TagDoesFileExistKO | ||
-} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove commented out code
There are times when it is advantageous to assert that a file "must already exist" on the file system and if it does not exist, a
FsResourceDoesNotExist
exception ought to be thrown. To enable these semantics through the API of thefs-api
/fs-sim
packages, I have added aMustExist
constructor to theAllowExisting
type.