optimize directory pattern searcher to avoid list files/directories without need
authorEugene Petrenko <eugene.petrenko@gmail.com>
Thu, 25 Aug 2011 08:58:24 +0000 (10:58 +0200)
committerEugene Petrenko <eugene.petrenko@gmail.com>
Thu, 25 Aug 2011 08:58:24 +0000 (10:58 +0200)
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternState.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/DirectoryScanner.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/FileSystemPath.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IDirectoryEntry.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealDirectoryEntry.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealRootDirectory.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/Wildcard.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/WildcardScanner2.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/DirectoryScannerMockFSTest.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestDirectoryScanner.java
nuget-tests/src/testng-nuget-fast.xml

index 3e26f8c5c895b5ef369cd5fb72a4463d8e6a1426..cc8fa2f68d2f8f11da3ea19cdaa573317a5039d2 100644 (file)
  */\r
 package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
 \r
+import org.jetbrains.annotations.Nullable;\r
+\r
 import java.util.ArrayList;\r
+import java.util.Collection;\r
 import java.util.List;\r
 \r
 public class AntPatternState {\r
@@ -26,6 +29,7 @@ public class AntPatternState {
   }\r
 \r
   private final List<Wildcard> myPatternParts;\r
+  //NDA state of mathing of pattern. Every ** produces new state\r
   private final List<Integer> myPatternPositions;\r
 \r
   public AntPatternState(List<Wildcard> patternParts, List<Integer> patternPositions) {\r
@@ -65,6 +69,36 @@ public class AntPatternState {
     }\r
   }\r
 \r
+  /**\r
+   * @return list of next tokends that are matching or null of there are at least one ** in pattern\r
+   */\r
+  @Nullable\r
+  public Collection<String> nextTokes() {\r
+    List<String> result = new ArrayList<String>();\r
+    for (int position : myPatternPositions) {\r
+      Wildcard wd = myPatternParts.get(position);\r
+      //** is here\r
+      if (wd == null) return null;\r
+\r
+      if (wd.containsNoPatterns()) {\r
+        result.add(wd.Pattern());\r
+      } else {\r
+        return null;\r
+      }\r
+    }\r
+    return result;\r
+  }\r
+\r
+  public boolean hasLastState() {\r
+    final int totalStates = myPatternParts.size();\r
+\r
+    for (int position : myPatternPositions) {\r
+      if (position == totalStates - 1) return true;\r
+    }\r
+\r
+    return false;\r
+  }\r
+\r
 \r
   public AntPatternStateMatch Enter(String component) {\r
     if (myPatternParts.size() == 0) {\r
index 49bd9a55626f919ae4c44382cfae8b16d6ca01f0..51cc4a5a0ef34f5eea3314f68b4cf59d000a43e2 100644 (file)
@@ -19,10 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
 import org.jetbrains.annotations.NotNull;\r
 \r
 import java.io.File;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.List;\r
+import java.util.*;\r
 \r
 /// <summary>\r
 /// Nant-syntax wildcard matcher on file system trees\r
@@ -34,7 +31,7 @@ public class DirectoryScanner {
     return FindFiles(new RealFileSystem(), new RealDirectoryEntry(new FileSystemPath(root)), includes, excludes);\r
   }\r
 \r
-  private static Collection<File> FindFiles(IFileSystem fs, IDirectoryEntry root, Collection<String> includes, Collection<String> excludes) {\r
+  public static Collection<File> FindFiles(IFileSystem fs, IDirectoryEntry root, Collection<String> includes, Collection<String> excludes) {\r
     List<Wildcard> basePath = BuildSearchPrefix(root, fs.CaseSensitive());\r
 \r
     List<FileSystemPath> result = new ArrayList<FileSystemPath>();\r
@@ -45,7 +42,7 @@ public class DirectoryScanner {
             ToAntPatternState(fs, basePath, fs.CaseSensitive(), excludes)\r
     );\r
 \r
-    List<File> foundFiles = new ArrayList<File>();\r
+    Set<File> foundFiles = new TreeSet<File>();\r
     for (FileSystemPath path : result) {\r
       foundFiles.add(path.FilePath());\r
     }\r
@@ -80,7 +77,6 @@ public class DirectoryScanner {
     List<Wildcard> result = new ArrayList<Wildcard>();\r
     result.addAll(rootPrefix);\r
     result.addAll(wildcards);\r
-\r
     return result;\r
   }\r
 \r
@@ -106,38 +102,64 @@ public class DirectoryScanner {
 \r
   private static void FindFilesRec(IDirectoryEntry directory, List<FileSystemPath> result, List<AntPatternState> includeState, List<AntPatternState> excludeState) {\r
     LOG.debug("Scanning directory: " + directory.Name());\r
-    for (IFileEntry file : directory.Files()) {\r
-      List<AntPatternState> newState = new ArrayList<AntPatternState>();\r
 \r
-      if (!Any(includeState, file.Name(), Predicate(false, AntPatternState.MatchResult.YES), newState))\r
-        continue;\r
+    boolean mayContainFiles = false;\r
+    Collection<String> explicits = new ArrayList<String>();\r
+    for (AntPatternState state : includeState) {\r
+      final Collection<String> nextTokens = state.nextTokes();\r
+      if (nextTokens == null) {\r
+        explicits = null;\r
+        mayContainFiles = true;\r
+        break;\r
+      }\r
+      if (!mayContainFiles) {\r
+        mayContainFiles = state.hasLastState();\r
+      }\r
+      explicits.addAll(nextTokens);\r
+    }\r
 \r
-      newState.clear();\r
-      if (Any(excludeState, file.Name(), Predicate(false, AntPatternState.MatchResult.YES), newState))\r
-        continue;\r
+    if (mayContainFiles) {\r
+      for (IFileEntry file : explicits != null ? directory.Files(explicits) : directory.Files()) {\r
+        List<AntPatternState> newState = new ArrayList<AntPatternState>();\r
+\r
+        if (!Any(includeState, file.Name(), equal(AntPatternState.MatchResult.YES), newState))\r
+          continue;\r
+\r
+        if (Any(excludeState, file.Name(), equal(AntPatternState.MatchResult.YES), newState))\r
+          continue;\r
 \r
-      result.add(file.Path());\r
+        result.add(file.Path());\r
+      }\r
     }\r
 \r
-    for (IDirectoryEntry subEntry : directory.Subdirectories()) {\r
+\r
+    for (IDirectoryEntry subEntry : explicits != null ? directory.Subdirectories(explicits) : directory.Subdirectories()) {\r
       String name = subEntry.Name();\r
 \r
       List<AntPatternState> newIncludeState = new ArrayList<AntPatternState>();\r
-      if (!Any(includeState, name, Predicate(true, AntPatternState.MatchResult.NO), newIncludeState))\r
+      if (!Any(includeState, name, notEqual(AntPatternState.MatchResult.NO), newIncludeState))\r
         continue;\r
 \r
       List<AntPatternState> newExcludeState = new ArrayList<AntPatternState>();\r
-      if (Any(excludeState, name, Predicate(false, AntPatternState.MatchResult.YES), newExcludeState))\r
+      if (Any(excludeState, name, equal(AntPatternState.MatchResult.YES), newExcludeState))\r
         continue;\r
 \r
       FindFilesRec(subEntry, result, newIncludeState, newExcludeState);\r
     }\r
   }\r
 \r
-  public static AnyPredicate Predicate(final boolean not, final AntPatternState.MatchResult state) {\r
+  private static AnyPredicate notEqual(@NotNull final AntPatternState.MatchResult result) {\r
+    return new AnyPredicate() {\r
+      public boolean matches(AntPatternState.MatchResult r) {\r
+        return result != r;\r
+      }\r
+    };\r
+  }\r
+\r
+  private static AnyPredicate equal(@NotNull final AntPatternState.MatchResult result) {\r
     return new AnyPredicate() {\r
       public boolean matches(AntPatternState.MatchResult r) {\r
-        return not ? state != r : state == r;\r
+        return result == r;\r
       }\r
     };\r
   }\r
index d049ecb2b70636f75aad809f8e416d7c52d199e5..885aacf1382151aaeb6a17d2af65bb1fe568c3d9 100644 (file)
@@ -19,34 +19,30 @@ import org.jetbrains.annotations.NotNull;
 \r
 import java.io.File;\r
 \r
-public class FileSystemPath\r
-  {\r
-    private final File myPath;\r
-\r
-    public FileSystemPath(@NotNull String path)\r
-    {\r
-      while(path.endsWith("/") || path.endsWith("\\"))\r
-        path = path.substring(0, path.length()-1);\r
-      myPath = new File(path);\r
-    }\r
-\r
-    public FileSystemPath(File path) {\r
-      myPath = path;\r
-    }\r
-\r
-    @NotNull\r
-    public String Name()\r
-    {\r
-\r
-              String name = myPath.getName();\r
-        if (name == null || name.length() == 0) return myPath.getPath();\r
-        return name;\r
-\r
-    }\r
-\r
-    @NotNull\r
-    public File FilePath()\r
-    {\r
-      return myPath;\r
-    }\r
+public class FileSystemPath {\r
+  private final File myPath;\r
+\r
+  public FileSystemPath(@NotNull String path) {\r
+    while (path.endsWith("/") || path.endsWith("\\"))\r
+      path = path.substring(0, path.length() - 1);\r
+    myPath = new File(path);\r
+  }\r
+\r
+  public FileSystemPath(File path) {\r
+    myPath = path;\r
+  }\r
+\r
+  @NotNull\r
+  public String Name() {\r
+\r
+    String name = myPath.getName();\r
+    if (name == null || name.length() == 0) return myPath.getPath();\r
+    return name;\r
+\r
+  }\r
+\r
+  @NotNull\r
+  public File FilePath() {\r
+    return myPath;\r
   }\r
+}\r
index d4300593320151560486e8b45a7d52d78804cc60..c873501f35db224f6f0071c6d145a7904794ab6a 100644 (file)
@@ -18,16 +18,32 @@ package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;
 import org.jetbrains.annotations.NotNull;\r
 import org.jetbrains.annotations.Nullable;\r
 \r
+import java.util.Collection;\r
+\r
 public interface IDirectoryEntry {\r
-    @NotNull\r
-    String Name();\r
-\r
-    @Nullable\r
-    IDirectoryEntry Parent();\r
-      \r
-    @NotNull\r
-    IDirectoryEntry[] Subdirectories();\r
-\r
-    @NotNull\r
-    IFileEntry[] Files();\r
-  }\r
+  @NotNull\r
+  String Name();\r
+\r
+  @Nullable\r
+  IDirectoryEntry Parent();\r
+\r
+  @NotNull\r
+  IDirectoryEntry[] Subdirectories();\r
+\r
+  /**\r
+   * @param names names filter\r
+   * @return redured list of items filtered (if possible) by given names\r
+   */\r
+  @NotNull\r
+  IDirectoryEntry[] Subdirectories(Collection<String> names);\r
+\r
+  @NotNull\r
+  IFileEntry[] Files();\r
+\r
+  /**\r
+   * @param names names filter\r
+   * @return returns list of existing file names, i.e. subset of given names\r
+   */\r
+  @NotNull\r
+  IFileEntry[] Files(Collection<String> names);\r
+}\r
index 453c25e3a2fe2d1ae729cb3c4a948bc25245d18c..bb493fd7c737c5f16e7e3002ed56676df6c6d64d 100644 (file)
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull;
 import java.io.File;\r
 import java.io.FileFilter;\r
 import java.util.ArrayList;\r
+import java.util.Collection;\r
 import java.util.List;\r
 \r
 public class RealDirectoryEntry implements IDirectoryEntry {\r
@@ -77,6 +78,15 @@ public class RealDirectoryEntry implements IDirectoryEntry {
     }\r
   }\r
 \r
+  @NotNull\r
+  public IDirectoryEntry[] Subdirectories(Collection<String> names) {\r
+    List<IDirectoryEntry> entries = new ArrayList<IDirectoryEntry>(names.size());\r
+    for (String name : names) {\r
+      entries.add(new RealDirectoryEntry(new FileSystemPath(new File(FilePath(), name))));\r
+    }\r
+    return entries.toArray(new IDirectoryEntry[entries.size()]);\r
+  }\r
+\r
   private File FilePath() {\r
     String filePath = myPath.FilePath().getPath();\r
 \r
@@ -108,6 +118,17 @@ public class RealDirectoryEntry implements IDirectoryEntry {
     }\r
   }\r
 \r
+  @NotNull\r
+  public IFileEntry[] Files(Collection<String> names) {\r
+    List<IFileEntry> list = new ArrayList<IFileEntry>();\r
+    for (String name : names) {\r
+      final File file = new File(FilePath(), name);\r
+      if (!file.isFile()) continue;\r
+      list.add(new RealFileEntry(new FileSystemPath(file)));\r
+    }\r
+    return list.toArray(new IFileEntry[list.size()]);\r
+  }\r
+\r
   @Override\r
   public String toString() {\r
     return "{d:" + myPath.FilePath() + "|" + Name() + "}";\r
index 6f424b9ca2b2ea014c4eff868b92d7f3c99fd5b1..e7dcd66effab4a739c709b8ba48f27bcb32b7ab1 100644 (file)
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
 import java.io.File;\r
 import java.io.FileFilter;\r
 import java.util.ArrayList;\r
+import java.util.Collection;\r
 \r
 public class RealRootDirectory implements IDirectoryEntry\r
   {\r
@@ -63,11 +64,21 @@ public class RealRootDirectory implements IDirectoryEntry
     }\r
 \r
     @NotNull\r
+    public IDirectoryEntry[] Subdirectories(Collection<String> names) {\r
+      return Subdirectories();\r
+    }\r
+\r
+    @NotNull\r
     public IFileEntry[] Files()\r
     {\r
       return new IFileEntry[0];\r
     }\r
 \r
+    @NotNull\r
+    public IFileEntry[] Files(Collection<String> names) {\r
+      return new IFileEntry[0];\r
+    }\r
+\r
     @Override\r
     public String toString()\r
     {\r
index f75ce00c7f35c16696c8eb40c062f727550291dc..759e3031f10f757e7a20fe9fa598ff293d757c59 100644 (file)
@@ -21,97 +21,86 @@ import org.jetbrains.annotations.NotNull;
 import java.util.ArrayList;\r
 import java.util.List;\r
 \r
-public class Wildcard\r
-  {\r
-    private final String myPattern;\r
-    private final boolean myCaseSensitive;\r
+public class Wildcard {\r
+  private final String myPattern;\r
+  private final boolean myCaseSensitive;\r
 \r
-    public Wildcard(String pattern, boolean caseSensitive)\r
-    {\r
-      pattern = pattern.replaceAll("[\\*]+", "*");\r
-      myCaseSensitive = caseSensitive;\r
+  public Wildcard(String pattern, boolean caseSensitive) {\r
+    pattern = pattern.replaceAll("[\\*]+", "*");\r
+    myCaseSensitive = caseSensitive;\r
 \r
-      myPattern = !caseSensitive ? pattern.toLowerCase() : pattern;\r
-    }\r
+    myPattern = !caseSensitive ? pattern.toLowerCase() : pattern;\r
+  }\r
 \r
-    public String Pattern()\r
-    {\r
-      return myPattern;\r
-    }\r
+  public String Pattern() {\r
+    return myPattern;\r
+  }\r
 \r
-    public boolean IsMatch(@NotNull String str)\r
-    {\r
-      String pattern = myPattern;\r
+  public boolean IsMatch(@NotNull String str) {\r
+    String pattern = myPattern;\r
 \r
-      if (StringUtil.isEmptyOrSpaces(pattern))\r
-        return StringUtil.isEmptyOrSpaces(str);\r
+    if (StringUtil.isEmptyOrSpaces(pattern))\r
+      return StringUtil.isEmptyOrSpaces(str);\r
 \r
-      if (!myCaseSensitive)\r
-        str = str.toLowerCase();\r
+    if (!myCaseSensitive)\r
+      str = str.toLowerCase();\r
 \r
-      int patlen = pattern.length();\r
-      List<Integer> positions = new ArrayList<Integer>();\r
-      positions.add(0);\r
-      for (int j = 0; j < str.length(); j++)\r
-      {\r
-        char c = str.charAt(j);\r
+    int patlen = pattern.length();\r
+    List<Integer> positions = new ArrayList<Integer>();\r
+    positions.add(0);\r
+    for (int j = 0; j < str.length(); j++) {\r
+      char c = str.charAt(j);\r
 \r
-        boolean hasPositionsToMatch = false;\r
+      boolean hasPositionsToMatch = false;\r
 \r
-        int len = positions.size();\r
-        for (int i = 0; i < len; i++)\r
-        {\r
-          int pat = positions.get(i);\r
-          if (pat >= patlen || pat < 0)\r
-            continue;\r
+      int len = positions.size();\r
+      for (int i = 0; i < len; i++) {\r
+        int pat = positions.get(i);\r
+        if (pat >= patlen || pat < 0)\r
+          continue;\r
 \r
-          hasPositionsToMatch = true;\r
+        hasPositionsToMatch = true;\r
 \r
-          if (pattern.charAt(pat) == '*')\r
-          {\r
-            if (pat == patlen - 1)\r
-              return true;\r
+        if (pattern.charAt(pat) == '*') {\r
+          if (pat == patlen - 1)\r
+            return true;\r
 \r
-            if (MatchChars(pattern.charAt(pat + 1), c))\r
-            {\r
-              if (pat == patlen - 2 && j == str.length() - 1)\r
-                return true;\r
-              positions.add(pat + 2);\r
-            }\r
-          }\r
-          else\r
-          {\r
-            if (MatchChars(pattern.charAt(pat), c))\r
-            {\r
-              if (pat == patlen - 1 && j == str.length() - 1)\r
-                return true;\r
-\r
-              positions.set(i, positions.get(i) + 1);\r
-            }\r
-            else positions.set(i, -1);\r
+          if (MatchChars(pattern.charAt(pat + 1), c)) {\r
+            if (pat == patlen - 2 && j == str.length() - 1)\r
+              return true;\r
+            positions.add(pat + 2);\r
           }\r
-        }\r
+        } else {\r
+          if (MatchChars(pattern.charAt(pat), c)) {\r
+            if (pat == patlen - 1 && j == str.length() - 1)\r
+              return true;\r
 \r
-        if (!hasPositionsToMatch)\r
-          return false;\r
+            positions.set(i, positions.get(i) + 1);\r
+          } else positions.set(i, -1);\r
+        }\r
       }\r
 \r
-      for (Integer x : positions)\r
-      {\r
-        if (x == patlen - 1 && pattern.charAt(x) == '*')\r
-          return true;\r
-      }\r
-      return false;\r
+      if (!hasPositionsToMatch)\r
+        return false;\r
     }\r
 \r
-    private static boolean MatchChars(char pat, char c)\r
-    {\r
-      return pat == '?' || pat == c;\r
+    for (Integer x : positions) {\r
+      if (x == patlen - 1 && pattern.charAt(x) == '*')\r
+        return true;\r
     }\r
+    return false;\r
+  }\r
 \r
-    @Override\r
-    public String toString()\r
-    {\r
-      return "Wildcard{" + myPattern + "}";\r
-    }\r
+  private static boolean MatchChars(char pat, char c) {\r
+    return pat == '?' || pat == c;\r
+  }\r
+\r
+  @Override\r
+  public String toString() {\r
+    return "Wildcard{" + myPattern + "}";\r
+  }\r
+\r
+  public boolean containsNoPatterns() {\r
+    return !myPattern.contains("?") && !myPattern.contains("*");\r
   }\r
+}\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/WildcardScanner2.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/WildcardScanner2.java
new file mode 100644 (file)
index 0000000..fa3b715
--- /dev/null
@@ -0,0 +1,162 @@
+/*\r
+ * Copyright 2000-2011 JetBrains s.r.o.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+/**\r
+ * Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+ * Date: 24.08.11 22:21\r
+ */\r
+public class WildcardScanner2 {\r
+/*\r
+  public Collection<File> matchWildcards(@NotNull final File root,\r
+                                         @NotNull final Collection<String> includes,\r
+                                         @NotNull final Collection<String> excludes) {\r
+\r
+  }\r
+\r
+\r
+  private static class MatchState {\r
+    private final List<Wildcard> myUnmatchedWildcards;\r
+    private final File myRoot;\r
+\r
+    private MatchState(@NotNull final File root, List<Wildcard> unmatchedWildcards) {\r
+      myUnmatchedWildcards = unmatchedWildcards;\r
+    }\r
+\r
+    @NotNull\r
+    public MatchResult match() {\r
+      assert myUnmatchedWildcards.size() > 0;\r
+      final Wildcard wd = myUnmatchedWildcards.iterator().next();\r
+\r
+      if (!wd.matches(name)) {\r
+        return new MatchResult(false, Collections.<MatchState>emptyList());\r
+      }\r
+\r
+      List<Wildcard> next = new ArrayList<Wildcard>(myUnmatchedWildcards);\r
+      List<MatchState> states = new ArrayList<MatchState>(2);\r
+\r
+      if (wd.isFork()) {\r
+        states.add(this);\r
+      }\r
+      next.remove(0);\r
+\r
+      if (next.isEmpty()) {\r
+        return new MatchResult(true, states);\r
+      } else {\r
+        states.add(new MatchState(next));\r
+        return new MatchResult(false, states);\r
+      }\r
+    }\r
+  }\r
+\r
+  private static class MatchResult {\r
+    private boolean myIsMatched;\r
+    private Collection<MatchState> myMatches;\r
+\r
+    private MatchResult(boolean isMatched, Collection<MatchState> matches) {\r
+      myIsMatched = isMatched;\r
+      myMatches = matches;\r
+    }\r
+\r
+    public boolean isIsMatched() {\r
+      return myIsMatched;\r
+    }\r
+\r
+    public Collection<MatchState> getMatches() {\r
+      return myMatches;\r
+    }\r
+  }\r
+\r
+  private abstract static class Wildcard {\r
+    protected final String myPattern;\r
+\r
+    protected Wildcard(@NotNull final String pattern) {\r
+      myPattern = pattern;\r
+    }\r
+\r
+    public abstract boolean matches(@NotNull final String name);\r
+    public abstract boolean isPattern();\r
+    public abstract boolean isFork();\r
+  }\r
+\r
+  private class NameWildcard extends Wildcard {\r
+    private NameWildcard(@NotNull String pattern) {\r
+      super(pattern);\r
+    }\r
+\r
+    @Override\r
+    public boolean matches(@NotNull String name) {\r
+      return myPattern.equals(name);\r
+    }\r
+\r
+    @Override\r
+    public boolean isPattern() {\r
+      return false;\r
+    }\r
+\r
+    @Override\r
+    public boolean isFork() {\r
+      return false;\r
+    }\r
+  }\r
+\r
+  private class PatternWildcard extends Wildcard {\r
+    private final Pattern myPattern;\r
+    private PatternWildcard(@NotNull String pattern) {\r
+      super(pattern);\r
+      myPattern = Pattern.compile("$" +\r
+              pattern.replaceAll("\\.", "\\.").replaceAll("\\*", ".*").replaceAll("\\?", ".?") + "^");\r
+    }\r
+\r
+    @Override\r
+    public boolean matches(@NotNull String name) {\r
+      return myPattern.matcher(name).matches();\r
+    }\r
+\r
+    @Override\r
+    public boolean isPattern() {\r
+      return true;\r
+    }\r
+\r
+    @Override\r
+    public boolean isFork() {\r
+      return false;\r
+    }\r
+  }\r
+\r
+  private class DoubleStarWildcard extends Wildcard {\r
+    private DoubleStarWildcard() {\r
+      super("**");\r
+    }\r
+\r
+    @Override\r
+    public boolean matches(@NotNull String name) {\r
+      return true;\r
+    }\r
+\r
+    @Override\r
+    public boolean isPattern() {\r
+      return true;\r
+    }\r
+\r
+    @Override\r
+    public boolean isFork() {\r
+      return true;\r
+    }\r
+  }\r
+*/\r
+}\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/DirectoryScannerMockFSTest.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/DirectoryScannerMockFSTest.java
new file mode 100644 (file)
index 0000000..c0daaf2
--- /dev/null
@@ -0,0 +1,71 @@
+/*\r
+ * Copyright 2000-2011 JetBrains s.r.o.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+import jetbrains.buildServer.BaseTestCase;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.*;\r
+import org.jmock.Expectations;\r
+import org.jmock.Mockery;\r
+import org.testng.annotations.Test;\r
+\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+\r
+/**\r
+ * Created by Eugene Petrenko (eugene.petrenko@gmail.com)\r
+ * Date: 24.08.11 22:05\r
+ */\r
+public class DirectoryScannerMockFSTest extends BaseTestCase {\r
+  @Test\r
+  public void test_should_not_list_folders_for_known_paths() {\r
+    Mockery m = new Mockery();\r
+    final IFileSystem fs = m.mock(IFileSystem.class);\r
+    final IDirectoryEntry root = m.mock(IDirectoryEntry.class, "root");\r
+    final IDirectoryEntry a = m.mock(IDirectoryEntry.class, "a");\r
+    final IDirectoryEntry proot = m.mock(IDirectoryEntry.class, "proot");\r
+    final IDirectoryEntry fsRoot = m.mock(IDirectoryEntry.class, "fsRoot");\r
+    final IFileEntry c_txt = m.mock(IFileEntry.class, "c.txt");\r
+\r
+    m.checking(new Expectations(){{\r
+      allowing(fs).CaseSensitive(); will(returnValue(true));\r
+      allowing(fs).Root(); will(returnValue(fsRoot));\r
+      oneOf(fs).IsPathAbsolute("a/c.txt"); will(returnValue(false));\r
+\r
+      allowing(fsRoot).Name(); will(returnValue("fsRoot"));\r
+      allowing(fsRoot).Parent(); will(returnValue(null));\r
+      allowing(fsRoot).Subdirectories(Arrays.asList("root")); will(returnValue(new IDirectoryEntry[]{ root} ));\r
+\r
+      allowing(root).Parent(); will(returnValue(proot));\r
+      allowing(root).Name(); will(returnValue("root"));\r
+      allowing(root).Subdirectories(Arrays.asList("a")); will(returnValue(new IDirectoryEntry[] { a }));\r
+      allowing(root).Files(Arrays.asList("a")); will(returnValue(new IFileEntry[0]));\r
+      allowing(proot).Parent(); will(returnValue(null));\r
+      allowing(proot).Name(); will(returnValue("proot"));\r
+\r
+      allowing(a).Name(); will(returnValue("a"));\r
+      allowing(a).Files(Arrays.asList("c.txt")); will(returnValue(new IFileEntry[]{c_txt} ));\r
+      allowing(a).Subdirectories(Arrays.asList("c.txt")); will(returnValue(new IDirectoryEntry[0]));\r
+\r
+      allowing(c_txt).Name(); will(returnValue("c.txt"));\r
+      allowing(c_txt).Path(); will(returnValue(new FileSystemPath("ccc")));\r
+    }});\r
+\r
+    DirectoryScanner.FindFiles(fs, root, Arrays.asList("a/c.txt"), Collections.<String>emptyList());\r
+\r
+    m.assertIsSatisfied();\r
+  }\r
+}\r
index 0951b727cb5ee119f234def72d427f676309c146..2000561094171beff15fb5b1408199c7a9613d00 100644 (file)
@@ -50,9 +50,7 @@ public class TestDirectoryScanner extends BaseTestCase {
     final Iterator<File> eIt = expected.iterator();\r
     final Iterator<File> aIt = actual.iterator();\r
 \r
-    for (int i = 0; i < expected.size(); i++)\r
-\r
-    {\r
+    for (int i = 0; i < expected.size(); i++) {\r
       final File eNext = eIt.next();\r
       final File aNext = aIt.next();\r
       Assert.assertEquals(PreparePath(eNext), PreparePath(aNext));\r
@@ -66,10 +64,11 @@ public class TestDirectoryScanner extends BaseTestCase {
       if (f.startsWith("f:")) {\r
         FileUtil.createParentDirs(path);\r
         FileUtil.writeFile(path, "text");\r
-      } else if (f.startsWith("d:"))\r
+      } else if (f.startsWith("d:")) {\r
         path.mkdirs();\r
-      else\r
+      } else {\r
         Assert.fail("Wrong fsDescription: " + f);\r
+      }\r
     }\r
   }\r
 \r
index a3e30c185d791ffcac0f08c3fa493b99003c9c40..2216de4ef72f351218791375501318c11f7293f4 100644 (file)
@@ -8,6 +8,7 @@
       <class name="jetbrains.buildServer.nuget.tests.util.fsScanner.TestDirectoryScanner"/>\r
       <class name="jetbrains.buildServer.nuget.tests.util.fsScanner.TestReadFileSystem"/>\r
       <class name="jetbrains.buildServer.nuget.tests.util.fsScanner.TestWildcard"/>\r
+      <class name="jetbrains.buildServer.nuget.tests.util.fsScanner.DirectoryScannerMockFSTest"/>\r
     </classes>\r
   </test>\r
 \r