Skip to content
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

renameFile now consistently reports an error if the destination is a directory #8

Merged
merged 1 commit into from
Mar 4, 2015

Conversation

gintas
Copy link

@gintas gintas commented Nov 3, 2014

I only tested on Windows, could you please run the tests on Unix to make sure they are not broken?

https://ghc.haskell.org/trac/ghc/ticket/8482 is related.

…directory, as specified by documentation.

Previously the exceptions raised would be quite inconsistent. For example,
given a file 'f' and a directory 'd', on Linux, the simple case worked:

Prelude System.Directory> renameFile "f" "d"
*** Exception: f: rename: inappropriate type (Is a directory)

however:

Prelude System.Directory> renameFile "f" "d/"
*** Exception: f: rename: inappropriate type (Not a directory)
Prelude System.Directory> renameFile "f" "."
*** Exception: e: rename: resource busy (Device or resource busy)
Prelude System.Directory> renameFile "f" "/tmp"
*** Exception: e: rename: unsatisified constraints (Directory not empty)

Windows was inconsistent with the documentation even in the general case:

Prelude System.Directory> renameFile "f" "d"
*** Exception: f: MoveFileEx "f" "d": permission denied (Access is denied.)

The additional check should not incur noticeable cost as an extra stat
to check for a directory is only performed in case of an IO exception.

I am not sure if this is actually the right abstraction level to fix
these inconsistencies. Perhaps they should be pushed down to libraries/Win32,
but the thing is, the Win32 documentation does not try to specify which
errors are raised in which settings, but System.Directory does, and the
implementation goes against the documentation, which seems wrong.
@hvr hvr modified the milestone: 1.2.1.2 Dec 19, 2014
@dcoutts
Copy link
Contributor

dcoutts commented Jan 19, 2015

This looks like a similar issue as we're discussing in #10 and #4, that after an operation we need to check if it's a dir or not to distinguish certain error cases. The subtlety is what to do when that "is it a dir" check itself fails (e.g. because it does not exist, or has a perm error or whatever). We should look around for other instances of this within directory and try and deal with them consistently.

checkNotDir opath
doRename `E.catch` renameExcHandler
where checkNotDir path = do
isdir <- pathIsDir path `E.catch` ((\ _ -> return False) :: IOException -> IO Bool)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use catchIOError to avoid specifying the type signature.

On second thought, I'm not sure if catchIOError is available in older versions of GHC. It is for 7.4 at least.

@Rufflewind
Copy link
Member

Certain race conditions can still cause the bug to reappear, but I'm not sure if there's a way to avoid this problem entirely.

@Rufflewind Rufflewind modified the milestones: 1.2.2, 1.2.2.1 Mar 3, 2015
Rufflewind added a commit to Rufflewind/directory that referenced this pull request Mar 4, 2015
@Rufflewind Rufflewind self-assigned this Mar 4, 2015
@Rufflewind Rufflewind merged commit 60667c8 into haskell:master Mar 4, 2015
Rufflewind added a commit to Rufflewind/directory that referenced this pull request Mar 4, 2015
Rufflewind added a commit to Rufflewind/directory that referenced this pull request Mar 4, 2015
@Rufflewind Rufflewind removed their assignment Apr 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants