From cc40beb2fa718b77152ba81a8ce663c58e314ab8 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 26 May 2015 15:35:41 -0700
Subject: [PATCH] file functions bug fixes

---
 .../r/nodes/builtin/base/FileFunctions.java   | 32 ++++++++++++-------
 .../com/oracle/truffle/r/runtime/Utils.java   |  2 +-
 2 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index 2c2135d960..91e7aafb10 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -525,6 +525,9 @@ public class FileFunctions {
     // TODO Implement all the options
     @RBuiltin(name = "list.files", kind = INTERNAL, parameterNames = {"path", "pattern", "all.files", "full.names", "recursive", "ignore.case", "include.dirs", "no.."})
     public abstract static class ListFiles extends RBuiltinNode {
+        private static final String DOT = ".";
+        private static final String DOTDOT = "..";
+
         @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
@@ -548,7 +551,7 @@ public class FileFunctions {
             return doListFilesBody(vec, pattern, allFiles, fullNames, recursive, ignoreCase, includeDirs, noDotDot);
         }
 
-        protected RStringVector doListFilesBody(RAbstractStringVector vec, String pattern, byte allFilesL, byte fullNamesL, byte recursiveL, byte ignoreCaseL, byte includeDirsL, byte noDotDotL) {
+        protected RStringVector doListFilesBody(RAbstractStringVector vec, String patternString, byte allFilesL, byte fullNamesL, byte recursiveL, byte ignoreCaseL, byte includeDirsL, byte noDotDotL) {
             controlVisibility();
             boolean allFiles = RRuntime.fromLogical(allFilesL);
             boolean fullNames = RRuntime.fromLogical(fullNamesL);
@@ -557,6 +560,7 @@ public class FileFunctions {
             boolean ignoreCase = check(ignoreCaseL, "ignoreCase");
             boolean includeDirs = !recursive || RRuntime.fromLogical(includeDirsL);
             boolean noDotDot = RRuntime.fromLogical(noDotDotL);
+            Pattern pattern = patternString == null ? null : Pattern.compile(patternString);
             // Curiously the result is not a vector of same length as the input,
             // as typical for R, but a single vector, which means duplicates may occur
             ArrayList<String> files = new ArrayList<>();
@@ -568,12 +572,11 @@ public class FileFunctions {
                     continue;
                 }
                 Path rootPath = root.toPath();
-                try (Stream<Path> stream = Files.find(rootPath, recursive ? Integer.MAX_VALUE : 1, new FileMatcher(pattern, allFiles, includeDirs, noDotDot))) {
+                try (Stream<Path> stream = Files.find(rootPath, recursive ? Integer.MAX_VALUE : 1, new FileMatcher(pattern, allFiles, includeDirs))) {
                     Iterator<Path> iter = stream.iterator();
                     Path vecPath = null;
                     if (!fullNames) {
-                        FileSystem fileSystem = FileSystems.getDefault();
-                        vecPath = fileSystem.getPath(vecPathString);
+                        vecPath = FileSystems.getDefault().getPath(vecPathString);
                     }
                     while (iter.hasNext()) {
                         Path file = iter.next();
@@ -585,6 +588,18 @@ public class FileFunctions {
                         }
                         files.add(file.toString());
                     }
+                    /*
+                     * Annoyingly "." and ".." are never visited by Files.find, so we have to
+                     * process them manually.
+                     */
+                    if (!noDotDot) {
+                        if (pattern == null || pattern.matcher(DOT).find()) {
+                            files.add(fullNames ? FileSystems.getDefault().getPath(vecPathString, DOT).toString() : DOT);
+                        }
+                        if (pattern == null || pattern.matcher(DOTDOT).find()) {
+                            files.add(fullNames ? FileSystems.getDefault().getPath(vecPathString, DOTDOT).toString() : DOTDOT);
+                        }
+                    }
                 } catch (IOException ex) {
                     // ignored
                 }
@@ -611,14 +626,12 @@ public class FileFunctions {
         private static class FileMatcher implements BiPredicate<Path, BasicFileAttributes> {
             final Pattern pattern;
             final boolean includeDirs;
-            final boolean noDotDot;
             final boolean allFiles;
 
-            FileMatcher(String pattern, boolean allFiles, boolean includeDirs, boolean noDotDot) {
+            FileMatcher(Pattern pattern, boolean allFiles, boolean includeDirs) {
                 this.allFiles = allFiles;
                 this.includeDirs = includeDirs;
-                this.noDotDot = noDotDot;
-                this.pattern = pattern == null ? null : Pattern.compile(pattern);
+                this.pattern = pattern;
             }
 
             public boolean test(Path path, BasicFileAttributes u) {
@@ -628,9 +641,6 @@ public class FileFunctions {
                 if (!allFiles && path.getFileName().toString().charAt(0) == '.') {
                     return false;
                 }
-                if (noDotDot && path.getFileName().toString().equals("..")) {
-                    return false;
-                }
                 if (pattern == null) {
                     return true;
                 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index 39101765e3..fc7360db1d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -276,7 +276,7 @@ public final class Utils {
                  * support in Java as much of it works relative to the initial setting.
                  */
                 if (path.length() == 0) {
-                    return wdState().getCurrentPath().toString();
+                    return keepRelative ? path : wdState().getCurrentPath().toString();
                 } else {
                     Path p = wdState().getFileSystem().getPath(path);
                     if (p.isAbsolute()) {
-- 
GitLab