Skip to content

Commit

Permalink
[fix] work-around File.exist when ending with '/'
Browse files Browse the repository at this point in the history
... MRI always returns false when path is a file (dir works)
the work-around here is java.io.File's path normalization

resolves GH-4403
  • Loading branch information
kares committed Jun 19, 2018
1 parent 0411d68 commit f4d76f5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
24 changes: 12 additions & 12 deletions core/src/main/java/org/jruby/util/JRubyFile.java
Expand Up @@ -52,7 +52,13 @@ public class JRubyFile extends JavaSecuredFile {
private static final long serialVersionUID = 435364547567567L;

public static JRubyFile create(String cwd, String pathname) {
return createNoUnicodeConversion(cwd, pathname);
if (pathname == null || pathname.length() == 0 || Ruby.isSecurityRestricted()) {
return JRubyFile.DUMMY;
}
if (pathname.startsWith("file:")) {
pathname = pathname.substring(5);
}
return createNoUnicodeConversion(cwd, pathname, new File(pathname));
}

public static FileResource createResource(ThreadContext context, String pathname) {
Expand Down Expand Up @@ -109,23 +115,13 @@ private static FileResource createResource(Ruby runtime, String cwd, String path
}

// If any other special resource types fail, count it as a filesystem backed resource.
return new RegularFileResource(runtime != null ? runtime.getPosix() : null, create(cwd, pathname));
return new RegularFileResource(runtime != null ? runtime.getPosix() : null, create(cwd, pathname), pathname);
}

public static String normalizeSeps(String path) {
return Platform.IS_WINDOWS ? path.replace(File.separatorChar, '/') : path;
}

private static JRubyFile createNoUnicodeConversion(String cwd, String pathname) {
if (pathname == null || pathname.length() == 0 || Ruby.isSecurityRestricted()) {
return JRubyFile.DUMMY;
}
if (pathname.startsWith("file:")) {
pathname = pathname.substring(5);
}
return createNoUnicodeConversion(cwd, pathname, new File(pathname));
}

private static JRubyFile createNoUnicodeConversion(String cwd, String pathname, File path) {
// File and company do not seem to recognize bare \ and / on Windows as absolute. Cheat!
if (path.isAbsolute() || Platform.IS_WINDOWS && (pathname.startsWith("/") || pathname.startsWith("\\"))) {
Expand Down Expand Up @@ -184,6 +180,10 @@ public String getPath() {
return normalizeSeps(super.getPath());
}

final String getPathDefault() {
return super.getPath();
}

@Override
public String toString() {
return normalizeSeps(super.toString());
Expand Down
24 changes: 17 additions & 7 deletions core/src/main/java/org/jruby/util/RegularFileResource.java
Expand Up @@ -29,16 +29,20 @@
* Represents a "regular" file, backed by regular file system.
*/
class RegularFileResource implements FileResource {

private final JRubyFile file;
private final String filePath; // original (non-normalized) file-path
private final POSIX posix;

RegularFileResource(POSIX posix, JRubyFile file) {
RegularFileResource(POSIX posix, JRubyFile file, String filePath) {
this.file = file;
this.filePath = filePath;
this.posix = posix;
}

protected RegularFileResource(POSIX posix, String filename) {
this.file = new JRubyFile(filename);
this.filePath = filename;
this.posix = posix;
}

Expand Down Expand Up @@ -91,7 +95,17 @@ private BasicFileAttributes readAttributes() throws IOException {

@Override
public boolean exists() {
return file.exists();
if (file.exists()) {
String path = filePath;
if (path.length() > 1 && path.charAt(path.length() - 1) == '/') {
path = file.getPathDefault();
if (path.length() > 0 && path.charAt(path.length() - 1) != '/' && !isDirectory()) {
return false;
}
}
return true;
}
return false;
}

@Override
Expand Down Expand Up @@ -123,11 +137,7 @@ public boolean isSymLink() {
BasicFileAttributes attrs = Files.readAttributes(file.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);

return attrs != null && attrs.isSymbolicLink();
} catch (SecurityException se) {
return false;
} catch (IOException ie) {
return false;
} catch (UnsupportedOperationException uoe) {
} catch (SecurityException|IOException|UnsupportedOperationException ex) {
return false;
}
}
Expand Down
9 changes: 9 additions & 0 deletions test/jruby/test_file.rb
Expand Up @@ -1406,4 +1406,13 @@ def test_realpath_with_uri_paths
assert_equal(result.end_with?(postfix), true, result + " ends with " + postfix)
end
end

def test_file_exists_ending_with_slash
assert File.exist?(__FILE__)
assert_false File.exist?(__FILE__ + '/')

assert File.exist?(File.dirname(__FILE__))
assert File.exist?(File.dirname(__FILE__) + '/')
end

end

0 comments on commit f4d76f5

Please sign in to comment.