File::hasWriteAccess

    if (!f.hasWriteAccess()) {

        setError("Cannot save to this location.  It is read-only.");

        return false;

    }

    if (!f.replaceWithText(doc)) {

        setError("Write failed. Disk space?");

        return false;

    }

I thought it was bullet proof :)

But hasWriteAccess() doesn't check that the folder is writable.  So the first check passes (the file has write access) then the second one fails because the replaceWithText actually requires that the folder has write access. 

I don't know if it's worth making hasWriteAccess() a bit cleverer ...? 

I guess that would happen if the file doesn't exist? If it did exist then the result should be correct, but TBH I'm not sure what the correct behaviour should be if you pass it a non-existent path..

No, the file has to exist for the error.  If the file doesn't exist you correctly check the directory permissions. 

The error happens like this: 

  • The directory (on the Mac) has permissions r-x.  
  • The file has permission rwx.  
  • replaceFileWIthText requires that the directory and path are writable because it will delete the original file and create a new one.  The final operation at least requires that the directory is rwx. 

I've fixed it for now with a double call to hasWriteAccess.  But if many operations are like replaceFileWithText, and i suspec that's a popular operation, then it would be more straightfoward to define: 

bool hasWriteAccess(bool alsoCheckParentFolder = true);

Which is probably a sensible course of action 90% of the time.