add new ant paths matcher
authorEugene.Petrenko <eugene.petrenko@gmail.com>
Wed, 24 Aug 2011 16:25:05 +0000 (18:25 +0200)
committerEugene.Petrenko <eugene.petrenko@gmail.com>
Wed, 24 Aug 2011 16:25:05 +0000 (18:25 +0200)
22 files changed:
.idea/projectCodeStyle.xml
README
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/MatchFilesBuildProcess.java
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternState.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternUtil.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/DirectoryScanner.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/FileSystemPath.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IDirectoryEntry.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IFileEntry.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IFileSystem.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealDirectoryEntry.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealFileEntry.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealFileSystem.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealRootDirectory.java [new file with mode: 0644]
nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/Wildcard.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/agent/MatchFilesBuildProcessTest.java
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/DirectoryFileFilesystemTest.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestAntPatternState.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestAntPatternUtil.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestDirectoryScanner.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestReadFileSystem.java [new file with mode: 0644]
nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestWildcard.java [new file with mode: 0644]

index 367c8611fc643ce38265172396da5984612173ca..c88cb986ce45405d1b56d1bc901a5e4d67d184c4 100644 (file)
@@ -2,7 +2,38 @@
 <project version="4">\r
   <component name="CodeStyleSettingsManager">\r
     <option name="PER_PROJECT_SETTINGS">\r
-      <value />\r
+      <value>\r
+        <ADDITIONAL_INDENT_OPTIONS fileType="java">\r
+          <option name="INDENT_SIZE" value="4" />\r
+          <option name="CONTINUATION_INDENT_SIZE" value="8" />\r
+          <option name="TAB_SIZE" value="4" />\r
+          <option name="USE_TAB_CHARACTER" value="false" />\r
+          <option name="SMART_TABS" value="false" />\r
+          <option name="LABEL_INDENT_SIZE" value="0" />\r
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />\r
+          <option name="USE_RELATIVE_INDENTS" value="false" />\r
+        </ADDITIONAL_INDENT_OPTIONS>\r
+        <ADDITIONAL_INDENT_OPTIONS fileType="jsp">\r
+          <option name="INDENT_SIZE" value="4" />\r
+          <option name="CONTINUATION_INDENT_SIZE" value="8" />\r
+          <option name="TAB_SIZE" value="4" />\r
+          <option name="USE_TAB_CHARACTER" value="false" />\r
+          <option name="SMART_TABS" value="false" />\r
+          <option name="LABEL_INDENT_SIZE" value="0" />\r
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />\r
+          <option name="USE_RELATIVE_INDENTS" value="false" />\r
+        </ADDITIONAL_INDENT_OPTIONS>\r
+        <ADDITIONAL_INDENT_OPTIONS fileType="xml">\r
+          <option name="INDENT_SIZE" value="4" />\r
+          <option name="CONTINUATION_INDENT_SIZE" value="8" />\r
+          <option name="TAB_SIZE" value="4" />\r
+          <option name="USE_TAB_CHARACTER" value="false" />\r
+          <option name="SMART_TABS" value="false" />\r
+          <option name="LABEL_INDENT_SIZE" value="0" />\r
+          <option name="LABEL_INDENT_ABSOLUTE" value="false" />\r
+          <option name="USE_RELATIVE_INDENTS" value="false" />\r
+        </ADDITIONAL_INDENT_OPTIONS>\r
+      </value>\r
     </option>\r
   </component>\r
 </project>\r
diff --git a/README b/README
index 82559c266e639169c8de984156ef1adcb2b1646d..12323a84b43a0b20b38a40389f1282205e731c2e 100644 (file)
--- a/README
+++ b/README
@@ -46,6 +46,7 @@ API gaps TeamCity:
    - user may tweak download url to download malicious file instead of expected one => checkes required
  - Add an API to provide pluginData path without use of ServerPaths class and specifying names explicitly
  - Extract interfaces from jetbrains.buildServer.controllers.admin.projects.EditBuildTypeFormFactory#getOrCreateForm to make it available in open API
+ - No Ant Path matcher component to convert relative and absolute patterns to list of files.
 
 API gaps NuGet:
  - Allow to call nuget.exe with plugins without installing them into %USERPROFILE%
index d2f60b851f6615c396459c75f766c090152740ef..5ee7ed179d29595dde14ae0a0d2b437dbf05de3f 100644 (file)
@@ -59,17 +59,25 @@ public class MatchFilesBuildProcess extends BuildProcessBase {
 \r
     final List<String> patterns = new ArrayList<String>();\r
     for (String _pattern : myParameters.getFiles()) {\r
-      final String pattern = _pattern.trim();\r
+      String pattern = _pattern.trim();\r
       if (StringUtil.isEmptyOrSpaces(pattern)) {\r
         continue;\r
       }\r
 \r
-      final File file = new File(pattern);\r
-      if (file.isAbsolute()) {\r
-        found = true;\r
-        LOG.debug("Found .nugkg to push: " + file);\r
-        myCallback.fileFound(file);\r
-        continue;\r
+      if (SystemInfo.isWindows\r
+              && (pattern.startsWith("/") || pattern.startsWith("\\"))\r
+              && !(pattern.startsWith("//") || pattern.startsWith("\\\\"))) {\r
+        pattern = pattern.substring(1);\r
+      }\r
+\r
+      if (!pattern.contains("*") && !pattern.contains("?")) {\r
+        final File file = new File(pattern);\r
+        if (file.isAbsolute()) {\r
+          found = true;\r
+          LOG.debug("Found .nugkg to push: " + file);\r
+          myCallback.fileFound(file);\r
+          continue;\r
+        }\r
       }\r
 \r
       patterns.add(pattern.replace('\\', '/'));\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternState.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternState.java
new file mode 100644 (file)
index 0000000..1d1da6f
--- /dev/null
@@ -0,0 +1,111 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+public class AntPatternState {\r
+  public enum MatchResult {\r
+    YES,\r
+    NO,\r
+    MAYBELATER\r
+  }\r
+\r
+  private final List<Wildcard> myPatternParts;\r
+  private final List<Integer> myPatternPositions;\r
+\r
+  public AntPatternState(List<Wildcard> patternParts, List<Integer> patternPositions) {\r
+    myPatternParts = patternParts;\r
+    myPatternPositions = patternPositions;\r
+  }\r
+\r
+  public AntPatternState(List<Wildcard> patternParts) {\r
+    this(patternParts, initialList());\r
+  }\r
+\r
+  private static List<Integer> initialList() {\r
+    List<Integer> list = new ArrayList<Integer>();\r
+    list.add(0);\r
+    return list;\r
+  }\r
+\r
+  public List<Integer> PatternPositions() {\r
+    return myPatternPositions;\r
+  }\r
+\r
+  public static class AntPatternStateMatch {\r
+    private final MatchResult myResult;\r
+    private final AntPatternState myState;\r
+\r
+    public AntPatternStateMatch(MatchResult result, AntPatternState state) {\r
+      myResult = result;\r
+      myState = state;\r
+    }\r
+\r
+    public MatchResult getResult() {\r
+      return myResult;\r
+    }\r
+\r
+    public AntPatternState getState() {\r
+      return myState;\r
+    }\r
+  }\r
+\r
+\r
+  public AntPatternStateMatch Enter(String component) {\r
+    if (myPatternParts.size() == 0) {\r
+      return new AntPatternStateMatch(MatchResult.NO, this);\r
+    }\r
+\r
+    MatchResult match = MatchResult.MAYBELATER;\r
+\r
+    //TODO:replace list with array operations\r
+\r
+    List<Integer> newPositions = new ArrayList<Integer>(myPatternPositions.size());\r
+    for (int pos : myPatternPositions) {\r
+      Wildcard wildcard = myPatternParts.get(pos);\r
+      if (wildcard != null) {\r
+        if (wildcard.IsMatch(component))\r
+          if (pos == myPatternParts.size() - 1)\r
+            match = MatchResult.YES;\r
+          else if (pos == myPatternParts.size() - 2 && myPatternParts.get(pos + 1) == null) {\r
+            match = MatchResult.YES;\r
+            newPositions.add(pos + 1);\r
+          } else newPositions.add(pos + 1);\r
+        else if (match == MatchResult.MAYBELATER) match = MatchResult.NO;\r
+      } else {\r
+        // **\r
+        newPositions.add(pos);\r
+\r
+        if (pos == myPatternParts.size() - 1)\r
+          match = MatchResult.YES;\r
+        else {\r
+          if (myPatternParts.get(pos + 1).IsMatch(component)) {\r
+            if (pos == myPatternParts.size() - 2)\r
+              match = MatchResult.YES;\r
+            else\r
+              newPositions.add(pos + 2);\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    return new AntPatternStateMatch(\r
+            match,\r
+            new AntPatternState(myPatternParts, newPositions));\r
+  }\r
+}
\ No newline at end of file
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternUtil.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/AntPatternUtil.java
new file mode 100644 (file)
index 0000000..100d1fc
--- /dev/null
@@ -0,0 +1,145 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import jetbrains.buildServer.util.StringUtil;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+public class AntPatternUtil\r
+  {\r
+    private static String NormalizePatternString(String pattern)\r
+    {\r
+      pattern = pattern.trim();\r
+      pattern = pattern.replace('\\', '/');\r
+      pattern = pattern.replaceAll("[//]+", "/");\r
+      pattern = pattern.replaceAll("\\*\\*[\\*]+", "**");\r
+      pattern = pattern.replaceAll("\\*\\*/\\*\\*", "**");\r
+      if (pattern.startsWith("/")) pattern = pattern.substring(1);\r
+      return pattern;\r
+    }\r
+\r
+    public static boolean IsFileNameMatch(String pattern, String name)\r
+    {\r
+      name = name.trim();\r
+      name = name.replace('\\', '/');\r
+      name = name.replaceAll("[//]+", "/");\r
+\r
+      List<Wildcard> wildcards = ParsePattern(pattern, false);\r
+      AntPatternState state = new AntPatternState(wildcards);\r
+\r
+      List<String> splitted = new ArrayList<String>(Arrays.asList(name.split("/")));\r
+      List<String> nameComponents = new ArrayList<String>();\r
+      for (String s : splitted)\r
+      {\r
+        if (!StringUtil.isEmptyOrSpaces(s))\r
+        {\r
+          nameComponents.add(s);\r
+        }\r
+      }\r
+\r
+      AntPatternState.MatchResult matchResult = AntPatternState.MatchResult.NO;\r
+\r
+      for (int i = 0; i < nameComponents.size(); i++)\r
+      {\r
+        if (nameComponents.get(i).equals(".") && i < nameComponents.size() - 1)\r
+          continue;\r
+\r
+        final AntPatternState.AntPatternStateMatch enter = state.Enter(nameComponents.get(i));\r
+        matchResult = enter.getResult();\r
+        state = enter.getState();\r
+      }\r
+\r
+      return matchResult == AntPatternState.MatchResult.YES;\r
+    }\r
+\r
+    public static List<Wildcard> ParsePattern(String pattern, boolean caseSensitive)\r
+    {\r
+      pattern = NormalizePatternString(pattern);\r
+      if (pattern.length() == 0)\r
+        return Collections.emptyList();\r
+\r
+      List<Wildcard> result = new ArrayList<Wildcard>();\r
+      for (String component : pattern.split("/"))\r
+      {\r
+        int astIndex = component.indexOf("**");\r
+        if (astIndex < 0)\r
+        {\r
+          result.add(new Wildcard(component, caseSensitive));\r
+          continue;\r
+        }\r
+\r
+        if (astIndex > 0)\r
+          result.add(new Wildcard(component.substring(0, astIndex) + "*", caseSensitive));\r
+\r
+        int cur = astIndex;\r
+        while (astIndex >= 0)\r
+        {\r
+          if (astIndex - cur > 0)\r
+            result.add(new Wildcard("*" + component.substring(cur, astIndex) + "*", caseSensitive));\r
+\r
+          result.add(null);\r
+\r
+          cur = astIndex + 2;\r
+          astIndex = component.indexOf("**", cur);\r
+        }\r
+\r
+        if (cur < component.length())\r
+          result.add(new Wildcard("*" + component.substring(cur), caseSensitive));\r
+      }\r
+\r
+      RemoveTwoDots(result);\r
+      RemoveOneDot(result);\r
+\r
+      return result;\r
+    }\r
+\r
+    private static void RemoveOneDot(List<Wildcard> wildcards)\r
+    {\r
+      int i = 0;\r
+      while (i < wildcards.size() - 1)\r
+      {\r
+        if (wildcards.get(i) != null && wildcards.get(i).Pattern().equals("."))\r
+          wildcards.remove(i);\r
+        else\r
+          i++;\r
+      }\r
+    }\r
+\r
+    private static void RemoveTwoDots(List<Wildcard> wildcards)\r
+    {\r
+      int i = 0;\r
+      while (i < wildcards.size() - 1)\r
+      {\r
+        if (wildcards.get(i + 1) != null && wildcards.get(i + 1).Pattern().equals(".."))\r
+        {\r
+          wildcards.remove(i);\r
+          wildcards.remove(i);\r
+\r
+          if (i > 0)\r
+            i--;\r
+        }\r
+        else\r
+          i++;\r
+      }\r
+\r
+      while (wildcards.size() > 0 && wildcards.get(0) != null && wildcards.get(0).Pattern().equals(".."))\r
+        wildcards.remove(0);\r
+    }\r
+  }\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/DirectoryScanner.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/DirectoryScanner.java
new file mode 100644 (file)
index 0000000..07bde59
--- /dev/null
@@ -0,0 +1,159 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import com.intellij.openapi.diagnostic.Logger;\r
+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
+\r
+/// <summary>\r
+/// Nant-syntax wildcard matcher on file system trees\r
+/// </summary>\r
+public class DirectoryScanner {\r
+  private static final Logger LOG = Logger.getInstance(DirectoryScanner.class.getName());\r
+\r
+  public static Collection<File> FindFiles(@NotNull File root, String[] includes, String[] excludes) {\r
+    return FindFiles(new RealFileSystem(), new RealDirectoryEntry(new FileSystemPath(root)), includes, excludes);\r
+  }\r
+\r
+  private static Collection<File> FindFiles(IFileSystem fs, IDirectoryEntry root, String[] includes, String[] excludes) {\r
+    List<Wildcard> basePath = BuildSearchPrefix(root, fs.CaseSensitive());\r
+\r
+    List<FileSystemPath> result = new ArrayList<FileSystemPath>();\r
+    FindFilesRec(\r
+            fs.Root(),\r
+            result,\r
+            ToAntPatternState(fs, basePath, fs.CaseSensitive(), includes),\r
+            ToAntPatternState(fs, basePath, fs.CaseSensitive(), excludes)\r
+    );\r
+\r
+    List<File> foundFiles = new ArrayList<File>();\r
+    for (FileSystemPath path : result) {\r
+      foundFiles.add(path.FilePath());\r
+    }\r
+    return foundFiles;\r
+  }\r
+\r
+  private static List<Wildcard> BuildSearchPrefix(@NotNull IDirectoryEntry root, boolean caseSensitive) {\r
+    List<Wildcard> wildcardPrefix = new ArrayList<Wildcard>();\r
+    while (root.Parent() != null) {\r
+      wildcardPrefix.add(new Wildcard(root.Name(), caseSensitive));\r
+      root = root.Parent();\r
+    }\r
+    Collections.reverse(wildcardPrefix);\r
+\r
+    return wildcardPrefix;\r
+  }\r
+\r
+  private static List<AntPatternState> ToAntPatternState(IFileSystem fs, List<Wildcard> wildcardPrefix, boolean caseSensitive, String[] patterns) {\r
+    List<AntPatternState> result = new ArrayList<AntPatternState>();\r
+    for (String x : patterns) {\r
+      result.add(new AntPatternState(ParsePattern(fs, wildcardPrefix, caseSensitive, x)));\r
+    }\r
+    return result;\r
+  }\r
+\r
+  private static List<Wildcard> ParsePattern(IFileSystem fs, List<Wildcard> rootPrefix, boolean caseSensitive, String pattern) {\r
+    List<Wildcard> wildcards = AntPatternUtil.ParsePattern(pattern, caseSensitive);\r
+\r
+    if (fs.IsPathAbsolute(pattern))\r
+      return wildcards;\r
+\r
+    List<Wildcard> result = new ArrayList<Wildcard>();\r
+    result.addAll(rootPrefix);\r
+    result.addAll(wildcards);\r
+\r
+    return result;\r
+  }\r
+\r
+  private interface AnyPredicate {\r
+    boolean matches(AntPatternState.MatchResult r);\r
+  }\r
+\r
+  private static boolean Any(List<AntPatternState> state, String component, AnyPredicate predicate, List<AntPatternState> newState) {\r
+    boolean any = false;\r
+\r
+    for (int i = 0; i < state.size(); i++) {\r
+      final AntPatternState.AntPatternStateMatch enter = state.get(i).Enter(component);\r
+      AntPatternState.MatchResult match = enter.getResult();\r
+      newState.add(i, enter.getState());\r
+\r
+      if (predicate.matches(match))\r
+        any = true;\r
+    }\r
+\r
+    return any;\r
+  }\r
+\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(), AntPredicateImpl.Predicate(false, AntPatternState.MatchResult.YES), newState))\r
+        continue;\r
+\r
+      newState.clear();\r
+      if (Any(excludeState, file.Name(), AntPredicateImpl.Predicate(false, AntPatternState.MatchResult.YES), newState))\r
+        continue;\r
+\r
+      result.add(file.Path());\r
+    }\r
+\r
+    for (IDirectoryEntry subEntry : directory.Subdirectories()) {\r
+      String name = subEntry.Name();\r
+\r
+      List<AntPatternState> newIncludeState = new ArrayList<AntPatternState>();\r
+      if (!Any(includeState, name, AntPredicateImpl.Predicate(true, AntPatternState.MatchResult.NO), newIncludeState))\r
+        continue;\r
+\r
+      List<AntPatternState> newExcludeState = new ArrayList<AntPatternState>();\r
+      if (Any(excludeState, name, AntPredicateImpl.Predicate(false, AntPatternState.MatchResult.YES), newExcludeState))\r
+        continue;\r
+\r
+      FindFilesRec(subEntry, result, newIncludeState, newExcludeState);\r
+    }\r
+  }\r
+\r
+  private static class AntPredicateImpl {\r
+    private final boolean myNegatiate;\r
+    private final AntPatternState.MatchResult myResult;\r
+\r
+    private AntPredicateImpl(boolean negatiate, AntPatternState.MatchResult result) {\r
+      myNegatiate = negatiate;\r
+      myResult = result;\r
+    }\r
+\r
+    private boolean AnyPredicateImpl(AntPatternState.MatchResult r) {\r
+      return myNegatiate ? myResult != r : myResult == r;\r
+    }\r
+\r
+\r
+    public static AnyPredicate Predicate(boolean not, AntPatternState.MatchResult state) {\r
+      final AntPredicateImpl antPredicate = new AntPredicateImpl(not, state);\r
+      return new AnyPredicate() {\r
+        public boolean matches(AntPatternState.MatchResult r) {\r
+          return antPredicate.AnyPredicateImpl(r);\r
+        }\r
+      };\r
+    }\r
+  }\r
+}\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/FileSystemPath.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/FileSystemPath.java
new file mode 100644 (file)
index 0000000..d049ecb
--- /dev/null
@@ -0,0 +1,52 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import org.jetbrains.annotations.NotNull;\r
+\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
+  }\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IDirectoryEntry.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IDirectoryEntry.java
new file mode 100644 (file)
index 0000000..d430059
--- /dev/null
@@ -0,0 +1,33 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import org.jetbrains.annotations.NotNull;\r
+import org.jetbrains.annotations.Nullable;\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
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IFileEntry.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IFileEntry.java
new file mode 100644 (file)
index 0000000..564b567
--- /dev/null
@@ -0,0 +1,22 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+public interface IFileEntry\r
+  {\r
+    String Name();\r
+    FileSystemPath Path();\r
+  }
\ No newline at end of file
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IFileSystem.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/IFileSystem.java
new file mode 100644 (file)
index 0000000..dd46ccb
--- /dev/null
@@ -0,0 +1,27 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+public interface IFileSystem {\r
+  boolean IsPathAbsolute(@NotNull String path);\r
+\r
+  @NotNull\r
+  IDirectoryEntry Root();\r
+\r
+  boolean CaseSensitive();\r
+}\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealDirectoryEntry.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealDirectoryEntry.java
new file mode 100644 (file)
index 0000000..453c25e
--- /dev/null
@@ -0,0 +1,115 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+\r
+import com.intellij.openapi.util.SystemInfo;\r
+import jetbrains.buildServer.util.StringUtil;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+import java.io.File;\r
+import java.io.FileFilter;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+public class RealDirectoryEntry implements IDirectoryEntry {\r
+  private final FileSystemPath myPath;\r
+\r
+  public RealDirectoryEntry(FileSystemPath path) {\r
+    myPath = path;\r
+  }\r
+\r
+  @NotNull\r
+  public String Name() {\r
+    {\r
+      String name = myPath.Name();\r
+      if (SystemInfo.isWindows) {\r
+        if (name.length() == 3 && name.charAt(1) == ':')\r
+          return name.charAt(0) + ":";\r
+      }\r
+\r
+      return name;\r
+    }\r
+  }\r
+\r
+  public IDirectoryEntry Parent() {\r
+    if (StringUtil.isEmptyOrSpaces(myPath.FilePath().getPath()))\r
+      return RealFileSystem.ROOT;\r
+\r
+    String parent = myPath.FilePath().getParent();\r
+    if (parent == null)\r
+      return RealFileSystem.ROOT;\r
+\r
+    FileSystemPath parentPath = new FileSystemPath(parent);\r
+    if (StringUtil.isEmptyOrSpaces(parentPath.FilePath().getPath()))\r
+      return RealFileSystem.ROOT;\r
+\r
+    return new RealDirectoryEntry(parentPath);\r
+  }\r
+\r
+  @NotNull\r
+  public IDirectoryEntry[] Subdirectories() {\r
+    try {\r
+      List<IDirectoryEntry> list = new ArrayList<IDirectoryEntry>();\r
+      for (File dir : FilePath().listFiles(new FileFilter() {\r
+        public boolean accept(File pathname) {\r
+          return pathname.isDirectory();\r
+        }\r
+      })) {\r
+        list.add(new RealDirectoryEntry(new FileSystemPath(dir)));\r
+      }\r
+      return list.toArray(new IDirectoryEntry[list.size()]);\r
+    } catch (Exception e) {\r
+      return new IDirectoryEntry[0];\r
+    }\r
+  }\r
+\r
+  private File FilePath() {\r
+    String filePath = myPath.FilePath().getPath();\r
+\r
+    if (SystemInfo.isWindows && filePath.endsWith(":")) {\r
+      return new File(filePath + "\\");\r
+    }\r
+    if (!SystemInfo.isWindows && filePath.equals("")) {\r
+      return new File("/");\r
+    }\r
+\r
+    return new File(filePath);\r
+  }\r
+\r
+  @NotNull\r
+  public IFileEntry[] Files() {\r
+\r
+    try {\r
+      List<IFileEntry> list = new ArrayList<IFileEntry>();\r
+      for (File dir : FilePath().listFiles(new FileFilter() {\r
+        public boolean accept(File pathname) {\r
+          return pathname.isFile();\r
+        }\r
+      })) {\r
+        list.add(new RealFileEntry(new FileSystemPath(dir)));\r
+      }\r
+      return list.toArray(new IFileEntry[list.size()]);\r
+    } catch (Exception e) {\r
+      return new IFileEntry[0];\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public String toString() {\r
+    return "{d:" + myPath.FilePath() + "|" + Name() + "}";\r
+  }\r
+}\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealFileEntry.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealFileEntry.java
new file mode 100644 (file)
index 0000000..af010f5
--- /dev/null
@@ -0,0 +1,37 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+public class RealFileEntry implements IFileEntry {\r
+  private final FileSystemPath myPath;\r
+\r
+  public RealFileEntry(FileSystemPath path) {\r
+    myPath = path;\r
+  }\r
+\r
+  public String Name() {\r
+    return myPath.Name();\r
+  }\r
+\r
+  public FileSystemPath Path() {\r
+    return myPath;\r
+  }\r
+\r
+  @Override\r
+  public String toString() {\r
+    return "{f:" + myPath.FilePath() + "|" + Name() + "}";\r
+  }\r
+}
\ No newline at end of file
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealFileSystem.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealFileSystem.java
new file mode 100644 (file)
index 0000000..a4a0e7e
--- /dev/null
@@ -0,0 +1,45 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import com.intellij.openapi.util.SystemInfo;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+import java.io.File;\r
+\r
+public class RealFileSystem implements IFileSystem {\r
+  public static final IDirectoryEntry ROOT = new RealRootDirectory();\r
+\r
+  public boolean IsPathAbsolute(@NotNull String path) {\r
+    if (SystemInfo.isWindows) {\r
+      if ((path.startsWith("/") || path.startsWith("\\")))\r
+        return false;\r
+\r
+      return new File(path).isAbsolute();\r
+    }\r
+    return path.startsWith("/");\r
+  }\r
+\r
+  @NotNull\r
+  public IDirectoryEntry Root() {\r
+    return ROOT;\r
+  }\r
+\r
+  public boolean CaseSensitive() {\r
+    return SystemInfo.isFileSystemCaseSensitive;\r
+  }\r
+}\r
+\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealRootDirectory.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/RealRootDirectory.java
new file mode 100644 (file)
index 0000000..6f424b9
--- /dev/null
@@ -0,0 +1,76 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import com.intellij.openapi.util.SystemInfo;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+import java.io.File;\r
+import java.io.FileFilter;\r
+import java.util.ArrayList;\r
+\r
+public class RealRootDirectory implements IDirectoryEntry\r
+  {\r
+    @NotNull\r
+    public String Name()\r
+    {\r
+      return "";\r
+    }\r
+\r
+    public IDirectoryEntry Parent()\r
+    {\r
+      return null;\r
+    }\r
+\r
+    @NotNull\r
+    public IDirectoryEntry[] Subdirectories()\r
+    {\r
+      {\r
+        ArrayList<IDirectoryEntry> result = new ArrayList<IDirectoryEntry>();\r
+        if (SystemInfo.isWindows)\r
+        {          \r
+          for (File drive : File.listRoots())\r
+          {\r
+            result.add(new RealDirectoryEntry(new FileSystemPath(drive)));\r
+          }         \r
+        } else\r
+        {\r
+          for (File ch : new File("/").listFiles(new FileFilter() {\r
+            public boolean accept(File pathname) {\r
+              return pathname.isDirectory();\r
+            }\r
+          }))\r
+          {\r
+            result.add(new RealDirectoryEntry(new FileSystemPath(ch)));\r
+          }\r
+        }\r
+\r
+        return result.toArray(new IDirectoryEntry[result.size()]);\r
+      }\r
+    }\r
+\r
+    @NotNull\r
+    public IFileEntry[] Files()\r
+    {\r
+      return new IFileEntry[0];\r
+    }\r
+\r
+    @Override\r
+    public String toString()\r
+    {\r
+      return "{d:FS_META_ROOT}";\r
+    }\r
+  }\r
diff --git a/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/Wildcard.java b/nuget-agent/src/jetbrains/buildServer/nuget/agent/runner/publish/fsScanner/Wildcard.java
new file mode 100644 (file)
index 0000000..f75ce00
--- /dev/null
@@ -0,0 +1,117 @@
+/*\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
+package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;\r
+\r
+import jetbrains.buildServer.util.StringUtil;\r
+import org.jetbrains.annotations.NotNull;\r
+\r
+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
+\r
+    public Wildcard(String pattern, boolean caseSensitive)\r
+    {\r
+      pattern = pattern.replaceAll("[\\*]+", "*");\r
+      myCaseSensitive = caseSensitive;\r
+\r
+      myPattern = !caseSensitive ? pattern.toLowerCase() : pattern;\r
+    }\r
+\r
+    public String Pattern()\r
+    {\r
+      return myPattern;\r
+    }\r
+\r
+    public boolean IsMatch(@NotNull String str)\r
+    {\r
+      String pattern = myPattern;\r
+\r
+      if (StringUtil.isEmptyOrSpaces(pattern))\r
+        return StringUtil.isEmptyOrSpaces(str);\r
+\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
+\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
+\r
+          hasPositionsToMatch = true;\r
+\r
+          if (pattern.charAt(pat) == '*')\r
+          {\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
+          }\r
+        }\r
+\r
+        if (!hasPositionsToMatch)\r
+          return false;\r
+      }\r
+\r
+      for (Integer x : positions)\r
+      {\r
+        if (x == patlen - 1 && pattern.charAt(x) == '*')\r
+          return true;\r
+      }\r
+      return false;\r
+    }\r
+\r
+    private static boolean MatchChars(char pat, char c)\r
+    {\r
+      return pat == '?' || pat == c;\r
+    }\r
+\r
+    @Override\r
+    public String toString()\r
+    {\r
+      return "Wildcard{" + myPattern + "}";\r
+    }\r
+  }\r
index 3fb0dc504660a5822bf67008c40deb1eb9586a36..845e69cd1e6351fa39097873bea1897b6e91862a 100644 (file)
@@ -220,6 +220,23 @@ public class MatchFilesBuildProcessTest extends BuildProcessTestCase {
   }\r
 \r
   @Test\r
+  public void test_match_full_file_wildcard3() throws RunBuildException {\r
+    final File dest = new File(root, "q/e/r/t/aaa.txt");\r
+    FileUtil.createParentDirs(dest);\r
+    FileUtil.writeFile(dest, "some content");\r
+\r
+    m.checking(new Expectations() {{\r
+      oneOf(cb).fileFound(dest);\r
+    }});\r
+\r
+    files.add(dest.getParentFile() + "/*");\r
+    assertRunSuccessfully(match, BuildFinishedStatus.FINISHED_SUCCESS);\r
+\r
+    m.assertIsSatisfied();\r
+  }\r
+\r
+\r
+  @Test\r
   public void test_match_fullPath_file2() throws RunBuildException {\r
     final File dest = new File(root, "a/b/c/aaa.txt");\r
     FileUtil.createParentDirs(dest);\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/DirectoryFileFilesystemTest.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/DirectoryFileFilesystemTest.java
new file mode 100644 (file)
index 0000000..0bc5074
--- /dev/null
@@ -0,0 +1,52 @@
+/*\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
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+import com.intellij.openapi.util.SystemInfo;\r
+import jetbrains.buildServer.BaseTestCase;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.RealFileSystem;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+public class DirectoryFileFilesystemTest extends BaseTestCase {\r
+  @Test\r
+  public void TestDirectoryRootsWindows() {\r
+    if (!SystemInfo.isWindows) return;\r
+\r
+    DoAbsTest("C:/", true);\r
+    DoAbsTest("C:\\", true);\r
+    DoAbsTest("\\", false);\r
+    DoAbsTest("/", false);\r
+    DoAbsTest("aaa", false);\r
+    DoAbsTest("aaa/vvv", false);\r
+    DoAbsTest("aaa\\vvv", false);\r
+    DoAbsTest("\\aaa\\vvv", false);\r
+    DoAbsTest("/aaa\\vvv", false);\r
+  }\r
+\r
+  @Test\r
+  public void TestDirectoryRootUnix() {\r
+    if (SystemInfo.isWindows) return;\r
+\r
+    DoAbsTest("/", true);\r
+    DoAbsTest("aaa/bbb", false);\r
+  }\r
+\r
+  private static void DoAbsTest(String path, boolean result) {\r
+    RealFileSystem fs = new RealFileSystem();\r
+    Assert.assertEquals(result, fs.IsPathAbsolute(path));\r
+  }\r
+}\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestAntPatternState.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestAntPatternState.java
new file mode 100644 (file)
index 0000000..f99bdde
--- /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
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+import jetbrains.buildServer.BaseTestCase;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.AntPatternState;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.AntPatternUtil;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.Wildcard;\r
+import org.jetbrains.annotations.Nullable;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+public class TestAntPatternState extends BaseTestCase {\r
+  private static void AssertPatternState(String pattern, @Nullable List<Integer> pos, String enter, String expectedResult) {\r
+    List<Wildcard> wildcards = AntPatternUtil.ParsePattern(pattern, false);\r
+\r
+    AntPatternState state = pos == null\r
+            ? new AntPatternState(wildcards)\r
+            : new AntPatternState(wildcards, pos);\r
+\r
+    final AntPatternState.AntPatternStateMatch e = state.Enter(enter);\r
+    AntPatternState.MatchResult match = e.getResult();\r
+    AntPatternState newState = e.getState();\r
+\r
+    StringBuilder sb = new StringBuilder();\r
+    sb.append(match);\r
+    sb.append(" ");\r
+    for (int p : newState.PatternPositions()) {\r
+      sb.append(p);\r
+      sb.append(":");\r
+    }\r
+\r
+    String result = sb.toString();\r
+    Assert.assertEquals(expectedResult, result);\r
+  }\r
+\r
+  @Test\r
+  public void PatternState() {\r
+    AssertPatternState("a*", null, "a", "YES ");\r
+    AssertPatternState("a*", null, "abc", "YES ");\r
+    AssertPatternState("a*", null, "b", "NO ");\r
+\r
+    AssertPatternState("a*/**", null, "b", "NO ");\r
+    AssertPatternState("a*/**", null, "a", "YES 1:");\r
+\r
+    AssertPatternState("**", null, "b", "YES 0:");\r
+    AssertPatternState("**/a", null, "b", "MAYBELATER 0:");\r
+    AssertPatternState("**/a", null, "a", "YES 0:");\r
+    AssertPatternState("**/a/**/a", Arrays.asList(0, 2), "a", "YES 0:2:2:"); // fix?\r
+\r
+    AssertPatternState("**/a/**/b", Arrays.asList(0, 2), "a", "MAYBELATER 0:2:2:");\r
+    AssertPatternState("**/a/**/b", Arrays.asList(0, 2), "b", "YES 0:2:");\r
+    AssertPatternState("**/a/**/b", Arrays.asList(0, 2), "c", "MAYBELATER 0:2:");\r
+  }\r
+}\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestAntPatternUtil.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestAntPatternUtil.java
new file mode 100644 (file)
index 0000000..64271df
--- /dev/null
@@ -0,0 +1,85 @@
+/*\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
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+\r
+import jetbrains.buildServer.BaseTestCase;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.AntPatternUtil;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.Wildcard;\r
+import jetbrains.buildServer.util.StringUtil;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+import java.util.List;\r
+\r
+public class TestAntPatternUtil extends BaseTestCase {\r
+  private static void AssertParseResult(String pattern, String expectedResult) {\r
+    List<Wildcard> wildcards = AntPatternUtil.ParsePattern(pattern, false);\r
+    StringBuilder sb = new StringBuilder();\r
+    for (Wildcard w : wildcards) {\r
+      sb.append(w == null ? "**" : w.Pattern());\r
+      sb.append(":");\r
+    }\r
+    String result = StringUtil.trimEnd(sb.toString(), ":");\r
+    Assert.assertEquals(expectedResult, result);\r
+  }\r
+\r
+  @Test\r
+  public void IsFileNameMatch() {\r
+    Assert.assertTrue(AntPatternUtil.IsFileNameMatch("a*/**b**", "abc/ss/aa/vv/ggbbhh/qq"));\r
+    Assert.assertFalse(AntPatternUtil.IsFileNameMatch("a*/**b**", "abc/ss/aa/vv/gghh/qq"));\r
+    Assert.assertTrue(AntPatternUtil.IsFileNameMatch("**/bin/**.exe", "My/BiN/Debug/program.exe"));\r
+    Assert.assertFalse(AntPatternUtil.IsFileNameMatch("**/bin/**.exe", "My/BiN/Debug/program.dll"));\r
+    Assert.assertTrue(AntPatternUtil.IsFileNameMatch("**/bin/**.exe", "bin/program.exe"));\r
+\r
+    Assert.assertTrue(AntPatternUtil.IsFileNameMatch("**aaa**ddd***ccc**", "aaa/aaa/ddd/ddd/ccc/ccc"));\r
+    Assert.assertFalse(AntPatternUtil.IsFileNameMatch("**aaa**ddd***ccc**", "aaa/aaa/ccc/ccc"));\r
+\r
+    Assert.assertTrue(AntPatternUtil.IsFileNameMatch(".\\s.slN", "S.sln"));\r
+    Assert.assertTrue(AntPatternUtil.IsFileNameMatch("s.slN", ".\\S.sln"));\r
+\r
+    Assert.assertFalse(AntPatternUtil.IsFileNameMatch(".", ""));\r
+  }\r
+\r
+  @Test\r
+  public void ParsePattern() {\r
+    AssertParseResult("a///\\\\bcd", "a:bcd");\r
+    AssertParseResult("//", "");\r
+    AssertParseResult("*****/**.exe", "**:*.exe");\r
+    AssertParseResult("**/bin/**.dll", "**:bin:**:*.dll"); // real-life example\r
+    AssertParseResult("**a**b**/bin", "**:*a*:**:*b*:**:bin");\r
+    AssertParseResult("a**a**b**", "a*:**:*a*:**:*b*:**");\r
+    AssertParseResult("**a**b**d", "**:*a*:**:*b*:**:*d");\r
+\r
+    AssertParseResult("../a/b/c", "a:b:c");\r
+    AssertParseResult("a/../b/../c", "c");\r
+    AssertParseResult("a/b/c/..", "a:b");\r
+    AssertParseResult("a/../../c", "c");\r
+    AssertParseResult("a/b/../../c", "c");\r
+    AssertParseResult("a/b/c/../../../d", "d");\r
+  }\r
+\r
+  @Test\r
+  public void TestParseLeadingSlash() {\r
+    AssertParseResult("/aaa/bbb/ccc", "aaa:bbb:ccc");\r
+  }\r
+\r
+  @Test\r
+  public void TestParseWindowsFullPath() {\r
+    AssertParseResult("c:/aaa/bbb/ccc", "c::aaa:bbb:ccc");\r
+  }\r
+\r
+}\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestDirectoryScanner.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestDirectoryScanner.java
new file mode 100644 (file)
index 0000000..be3dceb
--- /dev/null
@@ -0,0 +1,209 @@
+/*\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
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+\r
+import com.intellij.openapi.util.SystemInfo;\r
+import jetbrains.buildServer.BaseTestCase;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.DirectoryScanner;\r
+import jetbrains.buildServer.util.FileUtil;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
+\r
+public class TestDirectoryScanner extends BaseTestCase {\r
+  private void AssertScannerResult(String[] fsDescription, String[] includePatterns, String[] excludePatterns, String[] expectedResult) throws IOException {\r
+    File fsp = createTempDir();\r
+\r
+    CreateDirectories(fsDescription, fsp);\r
+    Collection<File> findFiles = DirectoryScanner.FindFiles(fsp, includePatterns, excludePatterns);\r
+\r
+    Set<File> expected = new TreeSet<File>();\r
+    for (String s : expectedResult) {\r
+      expected.add(new File(fsp, s));\r
+    }\r
+    Set<File> actual = new TreeSet<File>();\r
+\r
+    System.out.println("Found: ");\r
+    for (File file : findFiles) {\r
+      actual.add(file);\r
+      System.out.println("   " + file);\r
+    }\r
+\r
+    Assert.assertEquals(expected.size(), actual.size());\r
+    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
+      final File eNext = eIt.next();\r
+      final File aNext = aIt.next();\r
+      Assert.assertEquals(PreparePath(eNext), PreparePath(aNext));\r
+    }\r
+  }\r
+\r
+\r
+  private static void CreateDirectories(String[] fsDescription, File fsp) {\r
+    for (String f : fsDescription) {\r
+      File path = new File(fsp, f.substring(2));\r
+      if (f.startsWith("f:")) {\r
+        FileUtil.createParentDirs(path);\r
+        FileUtil.writeFile(path, "text");\r
+      } else if (f.startsWith("d:"))\r
+        path.mkdirs();\r
+      else\r
+        Assert.fail("Wrong fsDescription: " + f);\r
+    }\r
+  }\r
+\r
+\r
+  @Test\r
+  public void TestSmoke() throws IOException {\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "d:a",\r
+                            "f:a/a.exe",\r
+                            "f:a/a.dll",\r
+                            "f:a/a.ca",\r
+                    },\r
+            new String[]{"**"},\r
+            new String[]{"**/*.exe"},\r
+            new String[]{"a/a.ca", "a/a.dll"});\r
+  }\r
+\r
+  @Test\r
+  public void TestEmptyExclude() throws IOException {\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "d:a",\r
+                            "f:a/a.exe",\r
+                            "f:a/a.dll",\r
+                            "f:a/a.ca",\r
+                    },\r
+            new String[]{"**"},\r
+            new String[]{},\r
+            new String[]{"a/a.ca", "a/a.dll", "a/a.exe"});\r
+  }\r
+\r
+  @Test\r
+  public void TestEmptyInclude() throws IOException {\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "d:a",\r
+                            "f:a/a.exe",\r
+                            "f:a/a.dll",\r
+                            "f:a/a.ca",\r
+                    },\r
+            new String[]{},\r
+            new String[]{"**"},\r
+            new String[]{});\r
+  }\r
+\r
+  @Test\r
+  public void TestBothEmpty() throws IOException {\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "d:a",\r
+                            "f:a/a.exe",\r
+                            "f:a/a.dll",\r
+                            "f:a/a.ca",\r
+                    },\r
+            new String[]{},\r
+            new String[]{},\r
+            new String[]{});\r
+  }\r
+\r
+  @Test\r
+  public void TestShouldNotMatchDirectory() throws IOException {\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "f:a/b/c/d/e/f/g/h/i/p/g/aaa.txt",\r
+                            "d:a/r/c/d/e/f/g/h/i/p/g/aaa.txt",\r
+                    },\r
+            new String[]{"**/*.txt"},\r
+            new String[]{},\r
+            new String[]{"a/b/c/d/e/f/g/h/i/p/g/aaa.txt"});\r
+  }\r
+\r
+  @Test\r
+  public void TestCaseSensitive() throws IOException {\r
+    if (SystemInfo.isWindows) return;\r
+\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "f:a/b/c/d/e/f/g/h/i/p/g/aAa.txt",\r
+                            "f:a/r/e/a/l/f/g/h/i/p/g/aaa.txt",\r
+                    },\r
+            new String[]{"**/*A*.txt"},\r
+            new String[]{},\r
+            new String[]{"a/b/c/d/e/f/g/h/i/p/g/aAa.txt"});\r
+  }\r
+\r
+  @Test\r
+  public void TestCaseInSensitive() throws IOException {\r
+    if (SystemInfo.isWindows) return;\r
+\r
+    AssertScannerResult(\r
+            new String[]\r
+                    {\r
+                            "f:a/b/c/d/e/f/g/h/i/p/g/aAa.txt",\r
+                            "f:a/r/e/a/l/f/g/h/i/p/g/aaa.txt",\r
+                    },\r
+            new String[]{"**/*A*.txt"},\r
+            new String[]{},\r
+            new String[]\r
+                    {\r
+                            "a/b/c/d/e/f/g/h/i/p/g/aAa.txt",\r
+                            "a/r/e/a/l/f/g/h/i/p/g/aaa.txt",\r
+                    });\r
+  }\r
+\r
+\r
+  @Test\r
+  public void AbsoluteIncludePath() throws IOException {\r
+\r
+    File fsp = createTempDir();\r
+    File atxtFsp = new File(fsp, "a.txt");\r
+    FileUtil.writeFile(atxtFsp, "text");\r
+\r
+    Collection<File> files = DirectoryScanner.FindFiles(fsp, new String[]{atxtFsp.getPath()}, new String[0]);\r
+    Assert.assertEquals(1, files.size());\r
+    Assert.assertEquals(PreparePath(atxtFsp), PreparePath(files.iterator().next()));\r
+  }\r
+\r
+  private static String PreparePath(File f) {\r
+    String path = f.getPath();\r
+    path = path.replace('\\', '/');\r
+    if (!SystemInfo.isWindows) {\r
+      return path;\r
+    } else {\r
+      return path.toLowerCase();\r
+    }\r
+  }\r
+}\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestReadFileSystem.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestReadFileSystem.java
new file mode 100644 (file)
index 0000000..52253a3
--- /dev/null
@@ -0,0 +1,258 @@
+/*\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
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+\r
+import com.intellij.openapi.util.SystemInfo;\r
+import jetbrains.buildServer.BaseTestCase;\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.*;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+public class TestReadFileSystem extends BaseTestCase {\r
+  private interface FilesAction {\r
+    void action(RealDirectoryEntry r1, RealDirectoryEntry r2, RealDirectoryEntry r3, RealDirectoryEntry r4);\r
+  }\r
+\r
+\r
+  @Test\r
+  public void TestCaseSensitive() {\r
+    Assert.assertEquals(!SystemInfo.isWindows, new RealFileSystem().CaseSensitive());\r
+  }\r
+\r
+  private void TestFSTest(FilesAction a) throws IOException {\r
+\r
+    File path1 = createTempDir();\r
+    File path2 = new File(path1, "aaa");\r
+    File path3 = new File(path2, "bbb");\r
+    File path4 = new File(path3, "ccc");\r
+    path2.mkdirs();\r
+    path3.mkdirs();\r
+    path4.mkdirs();\r
+\r
+    RealDirectoryEntry r4 = new RealDirectoryEntry(new FileSystemPath(path4));\r
+    RealDirectoryEntry r3 = new RealDirectoryEntry(new FileSystemPath(path3));\r
+    RealDirectoryEntry r2 = new RealDirectoryEntry(new FileSystemPath(path2));\r
+    RealDirectoryEntry r1 = new RealDirectoryEntry(new FileSystemPath(path1));\r
+\r
+    a.action(r1, r2, r3, r4);\r
+\r
+  }\r
+\r
+\r
+  @Test\r
+  public void TestNames() throws IOException {\r
+    TestFSTest(new FilesAction() {\r
+      public void action(RealDirectoryEntry r1, RealDirectoryEntry r2, RealDirectoryEntry r3, RealDirectoryEntry r4) {\r
+        Assert.assertEquals("ccc", r4.Name());\r
+        Assert.assertEquals("bbb", r3.Name());\r
+        Assert.assertEquals("aaa", r2.Name());\r
+      }\r
+    });\r
+  }\r
+\r
+  @Test\r
+  public void TestParent() throws IOException {\r
+    TestFSTest(\r
+            new FilesAction() {\r
+              public void action(RealDirectoryEntry r1, RealDirectoryEntry r2, RealDirectoryEntry r3, RealDirectoryEntry r4) {\r
+                AssertDirectoriesEqual(r4.Parent(), r3);\r
+                AssertDirectoriesEqual(r4.Parent().Parent(), r2);\r
+                AssertDirectoriesEqual(r4.Parent().Parent().Parent(), r1);\r
+\r
+                AssertDirectoriesEqual(r3.Parent(), r2);\r
+                AssertDirectoriesEqual(r3.Parent().Parent(), r1);\r
+\r
+                AssertDirectoriesEqual(r2.Parent(), r1);\r
+\r
+\r
+              }\r
+            });\r
+  }\r
+\r
+  @Test\r
+  public void TestSubdirectories() throws IOException {\r
+    TestFSTest(\r
+            new FilesAction() {\r
+              public void action(RealDirectoryEntry r1, RealDirectoryEntry r2, RealDirectoryEntry r3, RealDirectoryEntry r4) {\r
+                Assert.assertEquals(0, r4.Subdirectories().length);\r
+                Assert.assertEquals(1, r3.Subdirectories().length);\r
+                Assert.assertEquals(1, r2.Subdirectories().length);\r
+                Assert.assertEquals(1, r1.Subdirectories().length);\r
+\r
+                AssertDirectoriesEqual(r3.Subdirectories()[0], r4);\r
+                AssertDirectoriesEqual(r2.Subdirectories()[0], r3);\r
+                AssertDirectoriesEqual(r1.Subdirectories()[0], r2);\r
+\r
+              }\r
+            });\r
+  }\r
+\r
+  @Test\r
+  public void TestRootSubdirectories() {\r
+    RealRootDirectory root = new RealRootDirectory();\r
+    Assert.assertTrue(root.Subdirectories().length > 0);\r
+  }\r
+\r
+  @Test(enabled = false)\r
+  public void TestRootSubdirectoriesWalk() {\r
+    int k = 10;\r
+    for (IDirectoryEntry sub1 : new RealRootDirectory().Subdirectories()) {\r
+      if (k-- < 0) break;\r
+      int j = 10;\r
+      for (IDirectoryEntry sub2 : sub1.Subdirectories()) {\r
+        if (j-- < 0) break;\r
+        int i = 10;\r
+        for (IDirectoryEntry sub3 : sub2.Subdirectories()) {\r
+          if (i-- < 0) break;\r
+          System.out.println("sub3 = " + sub3);\r
+        }\r
+      }\r
+    }\r
+\r
+  }\r
+\r
+\r
+  @Test\r
+  public void TestRealRoot() {\r
+    IDirectoryEntry root = RealFileSystem.ROOT;\r
+    DumpItem(root);\r
+    Assert.assertTrue(root.Subdirectories().length > 0);\r
+  }\r
+\r
+  private static void DumpItem(IDirectoryEntry e) {\r
+    Assert.assertNotNull(e);\r
+    System.out.println("entry = " + e);\r
+    for (IDirectoryEntry sub : e.Subdirectories()) {\r
+      System.out.println("entry->sub = " + sub);\r
+    }\r
+    for (IFileEntry fileEntry : e.Files()) {\r
+      System.out.println("entry->file = " + fileEntry);\r
+    }\r
+  }\r
+\r
+  @Test\r
+  public void TestSimpleUpDown() throws IOException {\r
+\r
+    File path = new File(createTempDir(), "aaa");\r
+    path.mkdirs();\r
+\r
+\r
+    IDirectoryEntry e = cd(path);\r
+    IDirectoryEntry p = e.Parent();\r
+    Assert.assertNotNull(p);\r
+\r
+    for (IDirectoryEntry dir : p.Subdirectories()) {\r
+      if (dir.Name().equals(e.Name())) {\r
+        AssertDirectoriesEqual(dir, e);\r
+        return;\r
+      }\r
+    }\r
+    Assert.fail("Failed to find child");\r
+  }\r
+\r
+\r
+  private static RealDirectoryEntry cd(File path) {\r
+    return new RealDirectoryEntry(new FileSystemPath(path));\r
+  }\r
+\r
+  @Test\r
+  public void TestShouldFindRootFS() throws IOException {\r
+    IDirectoryEntry r = cd(createTempDir());\r
+    while (true) {\r
+      IDirectoryEntry p = r.Parent();\r
+      if (p == null) break;\r
+      r = p;\r
+    }\r
+\r
+    Assert.assertNotNull(r);\r
+    Assert.assertEquals(r.getClass(), RealRootDirectory.class);\r
+  }\r
+\r
+  @Test\r
+  public void TestWalkUpAndDown() throws IOException {\r
+\r
+    File path = createTempDir();\r
+    for (String cc : new String[]{"a", "b", "c", "d", "e", "f", "g", "h"}) {\r
+      path = new File(path, cc);\r
+      path.mkdirs();\r
+    }\r
+\r
+    IDirectoryEntry test = new RealDirectoryEntry(new FileSystemPath(path));\r
+\r
+    List<String> loop = new ArrayList<String>();\r
+    while (true) {\r
+      System.out.println("p = " + test);\r
+      loop.add(test.Name());\r
+      IDirectoryEntry p = test.Parent();\r
+      if (p == null) break;\r
+      test = p;\r
+    }\r
+    Collections.reverse(loop);\r
+\r
+\r
+    IDirectoryEntry root = new RealRootDirectory();\r
+    Assert.assertEquals(root.Name(), loop.get(0));\r
+    loop.remove(0);\r
+\r
+    for (String name : loop) {\r
+      boolean found = false;\r
+      for (IDirectoryEntry sub : root.Subdirectories()) {\r
+        if (sub.Name().equals(name)) {\r
+          found = true;\r
+          root = sub;\r
+        }\r
+      }\r
+      if (!found) {\r
+        System.out.println("Looking for name '" + name + "{0}'");\r
+        System.out.println("Looking under    '" + root + "'");\r
+        DumpItem(root);\r
+\r
+        Assert.assertTrue(found, "Failed to find " + name + " under " + root);\r
+      }\r
+    }\r
+\r
+  }\r
+\r
+  private static void AssertDirectoriesEqual(IDirectoryEntry e1, IDirectoryEntry e2) {\r
+    Assert.assertEquals(e1.toString(), e2.toString());\r
+  }\r
+\r
+  @Test\r
+  public void TestEquality() throws IOException {\r
+    final File dir = createTempDir();\r
+    AssertDirectoriesEqual(new RealDirectoryEntry(new FileSystemPath(dir)), new RealDirectoryEntry(new FileSystemPath(dir)));\r
+  }\r
+\r
+  @Test\r
+  public void TestParentDirectory() throws IOException {\r
+    File path = createTempDir();\r
+\r
+    List<IDirectoryEntry> entries = new ArrayList<IDirectoryEntry>();\r
+    IDirectoryEntry e = new RealDirectoryEntry(new FileSystemPath(path));\r
+    while (e.Parent() != null) {\r
+      System.out.println("e = " + e);\r
+      entries.add(e);\r
+      e = e.Parent();\r
+    }\r
+  }\r
+}\r
diff --git a/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestWildcard.java b/nuget-tests/src/jetbrains/buildServer/nuget/tests/util/fsScanner/TestWildcard.java
new file mode 100644 (file)
index 0000000..63603f3
--- /dev/null
@@ -0,0 +1,60 @@
+/*\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
+package jetbrains.buildServer.nuget.tests.util.fsScanner;\r
+\r
+import jetbrains.buildServer.nuget.agent.runner.publish.fsScanner.Wildcard;\r
+import org.testng.Assert;\r
+import org.testng.annotations.Test;\r
+\r
+public class TestWildcard {\r
+  @Test\r
+  public void test_01() {\r
+    Assert.assertFalse(new Wildcard("abcd", true).IsMatch("a"));\r
+    Assert.assertFalse(new Wildcard("*.cs", true).IsMatch("hello.csc"));\r
+\r
+    Assert.assertTrue(new Wildcard("", true).IsMatch(""));\r
+    Assert.assertFalse(new Wildcard("", true).IsMatch("asdsad"));\r
+\r
+    Assert.assertTrue(new Wildcard("*.cs", true).IsMatch("hello.cs"));\r
+    Assert.assertTrue(new Wildcard("h*.cs", true).IsMatch("hello.cs"));\r
+    Assert.assertFalse(new Wildcard("a*.cs", true).IsMatch("hello.cs"));\r
+    Assert.assertTrue(new Wildcard("*.cs*", true).IsMatch("hello.cs"));\r
+    Assert.assertTrue(new Wildcard("*.cs", true).IsMatch(".cs"));\r
+    Assert.assertFalse(new Wildcard("*.cs", true).IsMatch("hello.s"));\r
+\r
+    Assert.assertTrue(new Wildcard("*a*c", true).IsMatch("1221abcccac"));\r
+    Assert.assertTrue(new Wildcard("a", true).IsMatch("a"));\r
+    Assert.assertTrue(new Wildcard("?", true).IsMatch("z"));\r
+    Assert.assertFalse(new Wildcard("*?*", true).IsMatch(""));\r
+    Assert.assertTrue(new Wildcard("*?*", true).IsMatch("k"));\r
+\r
+  }\r
+\r
+  @Test\r
+  public void test_02() {\r
+    Assert.assertTrue(new Wildcard("*?**", true).IsMatch("k"));\r
+    Assert.assertTrue(new Wildcard("*?*", true).IsMatch("111k"));\r
+    Assert.assertTrue(new Wildcard("*?*", true).IsMatch("11k22"));\r
+    Assert.assertTrue(new Wildcard("*?*m*", true).IsMatch("11mk22"));\r
+    Assert.assertFalse(new Wildcard("*??*m*", true).IsMatch("1mk22"));\r
+    Assert.assertTrue(\r
+            new Wildcard("*non-greedy character*matching", true).IsMatch(\r
+                    "non-greedy character matching compared to greedy character matching"));\r
+    Assert.assertFalse(\r
+            new Wildcard("*non-greedy character*matching2", true).IsMatch(\r
+                    "non-greedy character matching compared to greedy character matching"));\r
+  }\r
+}\r