aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcgdecker <cgdecker@google.com>2019-10-04 14:34:57 -0700
committerChris Povirk <beigetangerine@gmail.com>2019-10-04 20:58:25 -0400
commita25ca765fb81f68013dc69fb9ebe37c50ab98b7e (patch)
tree7439bca825b6a481993c7aa8fd1d4f78410ca039
parent1370e8f34be27a66c4560e23c17bf7c87fba7229 (diff)
downloadjimfs-a25ca765fb81f68013dc69fb9ebe37c50ab98b7e.tar.gz
Change Jimfs PathMatchers to use the regex flags indicated by the Configuration's canonical (rather than display) path normalization when the Configuration is set to use canonical normalization for path equality.
This basically affects Windows-like configurations, as Windows/NTFS is the only file system (at least of those Jimfs has a built-in equivalent for) that uses these settings. Essentially, Windows does not normalize the case of file names when displaying paths but it does normalize them (case fold) for comparison and equality. On a real Windows file system, a PathMatcher for "glob:**.txt" or "glob:**.TXT" would match both files ending in ".txt" and files ending in ".TXT". Fixes https://github.com/google/jimfs/issues/91 RELNOTES=Fixed behavior of `PathMatcher`s for Windows-like configurations to do case-insensitive matching. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=272959573
-rw-r--r--jimfs/src/main/java/com/google/common/jimfs/PathService.java7
-rw-r--r--jimfs/src/test/java/com/google/common/jimfs/JimfsWindowsLikeFileSystemTest.java8
-rw-r--r--jimfs/src/test/java/com/google/common/jimfs/PathServiceTest.java56
3 files changed, 68 insertions, 3 deletions
diff --git a/jimfs/src/main/java/com/google/common/jimfs/PathService.java b/jimfs/src/main/java/com/google/common/jimfs/PathService.java
index 39bac91..49717bd 100644
--- a/jimfs/src/main/java/com/google/common/jimfs/PathService.java
+++ b/jimfs/src/main/java/com/google/common/jimfs/PathService.java
@@ -199,6 +199,9 @@ final class PathService implements Comparator<JimfsPath> {
/** Creates a hash code for the given path. */
public int hash(JimfsPath path) {
+ // Note: JimfsPath.equals() is implemented using the compare() method below;
+ // equalityUsesCanonicalForm is taken into account there via the namesOrdering, which is set
+ // at construction time.
int hash = 31;
hash = 31 * hash + getFileSystem().hashCode();
@@ -251,7 +254,9 @@ final class PathService implements Comparator<JimfsPath> {
*/
public PathMatcher createPathMatcher(String syntaxAndPattern) {
return PathMatchers.getPathMatcher(
- syntaxAndPattern, type.getSeparator() + type.getOtherSeparators(), displayNormalizations);
+ syntaxAndPattern,
+ type.getSeparator() + type.getOtherSeparators(),
+ equalityUsesCanonicalForm ? canonicalNormalizations : displayNormalizations);
}
private static final Predicate<Object> NOT_EMPTY =
diff --git a/jimfs/src/test/java/com/google/common/jimfs/JimfsWindowsLikeFileSystemTest.java b/jimfs/src/test/java/com/google/common/jimfs/JimfsWindowsLikeFileSystemTest.java
index 8fbbb19..a3b7ad2 100644
--- a/jimfs/src/test/java/com/google/common/jimfs/JimfsWindowsLikeFileSystemTest.java
+++ b/jimfs/src/test/java/com/google/common/jimfs/JimfsWindowsLikeFileSystemTest.java
@@ -306,7 +306,9 @@ public class JimfsWindowsLikeFileSystemTest extends AbstractJimfsIntegrationTest
assertThatPath("C:\\foo\\bar\\baz\\stuff").matches("glob:C:\\\\foo\\\\**");
assertThatPath("C:\\foo\\bar\\baz\\stuff").matches("glob:C:\\\\**\\\\stuff");
assertThatPath("C:\\foo").matches("glob:C:\\\\[a-z]*");
- assertThatPath("C:\\Foo").doesNotMatch("glob:C:\\\\[a-z]*");
+ assertThatPath("C:\\Foo").matches("glob:C:\\\\[a-z]*");
+ assertThatPath("C:\\foo").matches("glob:C:\\\\[A-Z]*");
+ assertThatPath("C:\\Foo").matches("glob:C:\\\\[A-Z]*");
assertThatPath("C:\\foo\\bar\\baz\\Stuff.java").matches("glob:**\\\\*.java");
assertThatPath("C:\\foo\\bar\\baz\\Stuff.java").matches("glob:**\\\\*.{java,class}");
assertThatPath("C:\\foo\\bar\\baz\\Stuff.class").matches("glob:**\\\\*.{java,class}");
@@ -331,7 +333,9 @@ public class JimfsWindowsLikeFileSystemTest extends AbstractJimfsIntegrationTest
assertThatPath("C:\\foo\\bar\\baz\\stuff").matches("glob:C:/foo/**");
assertThatPath("C:\\foo\\bar\\baz\\stuff").matches("glob:C:/**/stuff");
assertThatPath("C:\\foo").matches("glob:C:/[a-z]*");
- assertThatPath("C:\\Foo").doesNotMatch("glob:C:/[a-z]*");
+ assertThatPath("C:\\Foo").matches("glob:C:/[a-z]*");
+ assertThatPath("C:\\foo").matches("glob:C:/[A-Z]*");
+ assertThatPath("C:\\Foo").matches("glob:C:/[A-Z]*");
assertThatPath("C:\\foo\\bar\\baz\\Stuff.java").matches("glob:**/*.java");
assertThatPath("C:\\foo\\bar\\baz\\Stuff.java").matches("glob:**/*.{java,class}");
assertThatPath("C:\\foo\\bar\\baz\\Stuff.class").matches("glob:**/*.{java,class}");
diff --git a/jimfs/src/test/java/com/google/common/jimfs/PathServiceTest.java b/jimfs/src/test/java/com/google/common/jimfs/PathServiceTest.java
index 6a98d69..65349c7 100644
--- a/jimfs/src/test/java/com/google/common/jimfs/PathServiceTest.java
+++ b/jimfs/src/test/java/com/google/common/jimfs/PathServiceTest.java
@@ -16,6 +16,7 @@
package com.google.common.jimfs;
+import static com.google.common.jimfs.PathNormalization.CASE_FOLD_ASCII;
import static com.google.common.jimfs.PathSubject.paths;
import static com.google.common.truth.Truth.assertAbout;
import static com.google.common.truth.Truth.assertThat;
@@ -25,6 +26,7 @@ import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
+import java.nio.file.PathMatcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -179,6 +181,56 @@ public class PathServiceTest {
.isInstanceOf(PathMatchers.RegexPathMatcher.class);
}
+ @Test
+ public void testPathMatcher_usingCanonicalForm_usesCanonicalNormalizations() {
+ // https://github.com/google/jimfs/issues/91
+ // This matches the behavior of Windows (the only built-in configuration that uses canonical
+ // form for equality). There, PathMatchers should do case-insensitive matching despite Windows
+ // not normalizing case for display.
+ assertCaseInsensitiveMatches(
+ new PathService(
+ PathType.unix(), NO_NORMALIZATIONS, ImmutableSet.of(CASE_FOLD_ASCII), true));
+ assertCaseSensitiveMatches(
+ new PathService(
+ PathType.unix(), ImmutableSet.of(CASE_FOLD_ASCII), NO_NORMALIZATIONS, true));
+ }
+
+ @Test
+ public void testPathMatcher_usingDisplayForm_usesDisplayNormalizations() {
+ assertCaseInsensitiveMatches(
+ new PathService(
+ PathType.unix(), ImmutableSet.of(CASE_FOLD_ASCII), NO_NORMALIZATIONS, false));
+ assertCaseSensitiveMatches(
+ new PathService(
+ PathType.unix(), NO_NORMALIZATIONS, ImmutableSet.of(CASE_FOLD_ASCII), false));
+ }
+
+ private static void assertCaseInsensitiveMatches(PathService service) {
+ ImmutableList<PathMatcher> matchers =
+ ImmutableList.of(
+ service.createPathMatcher("glob:foo"), service.createPathMatcher("glob:FOO"));
+
+ JimfsPath lowerCasePath = singleNamePath(service, "foo");
+ JimfsPath upperCasePath = singleNamePath(service, "FOO");
+ JimfsPath nonMatchingPath = singleNamePath(service, "bar");
+
+ for (PathMatcher matcher : matchers) {
+ assertThat(matcher.matches(lowerCasePath)).isTrue();
+ assertThat(matcher.matches(upperCasePath)).isTrue();
+ assertThat(matcher.matches(nonMatchingPath)).isFalse();
+ }
+ }
+
+ private static void assertCaseSensitiveMatches(PathService service) {
+ PathMatcher matcher = service.createPathMatcher("glob:foo");
+
+ JimfsPath lowerCasePath = singleNamePath(service, "foo");
+ JimfsPath upperCasePath = singleNamePath(service, "FOO");
+
+ assertThat(matcher.matches(lowerCasePath)).isTrue();
+ assertThat(matcher.matches(upperCasePath)).isFalse();
+ }
+
public static PathService fakeUnixPathService() {
return fakePathService(PathType.unix(), false);
}
@@ -194,6 +246,10 @@ public class PathServiceTest {
return service;
}
+ private static JimfsPath singleNamePath(PathService service, String name) {
+ return new JimfsPath(service, null, ImmutableList.of(Name.create(name, name)));
+ }
+
private static final FileSystem FILE_SYSTEM;
static {