2 * Copyright 2000-2011 JetBrains s.r.o.
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
16 package jetbrains.buildServer.nuget.agent.runner.publish.fsScanner;
\r
18 import com.intellij.openapi.diagnostic.Logger;
\r
19 import org.jetbrains.annotations.NotNull;
\r
21 import java.io.File;
\r
22 import java.util.ArrayList;
\r
23 import java.util.Collection;
\r
24 import java.util.Collections;
\r
25 import java.util.List;
\r
28 /// Nant-syntax wildcard matcher on file system trees
\r
30 public class DirectoryScanner {
\r
31 private static final Logger LOG = Logger.getInstance(DirectoryScanner.class.getName());
\r
33 public static Collection<File> FindFiles(@NotNull File root, String[] includes, String[] excludes) {
\r
34 return FindFiles(new RealFileSystem(), new RealDirectoryEntry(new FileSystemPath(root)), includes, excludes);
\r
37 private static Collection<File> FindFiles(IFileSystem fs, IDirectoryEntry root, String[] includes, String[] excludes) {
\r
38 List<Wildcard> basePath = BuildSearchPrefix(root, fs.CaseSensitive());
\r
40 List<FileSystemPath> result = new ArrayList<FileSystemPath>();
\r
44 ToAntPatternState(fs, basePath, fs.CaseSensitive(), includes),
\r
45 ToAntPatternState(fs, basePath, fs.CaseSensitive(), excludes)
\r
48 List<File> foundFiles = new ArrayList<File>();
\r
49 for (FileSystemPath path : result) {
\r
50 foundFiles.add(path.FilePath());
\r
55 private static List<Wildcard> BuildSearchPrefix(@NotNull IDirectoryEntry root, boolean caseSensitive) {
\r
56 List<Wildcard> wildcardPrefix = new ArrayList<Wildcard>();
\r
57 while (root.Parent() != null) {
\r
58 wildcardPrefix.add(new Wildcard(root.Name(), caseSensitive));
\r
59 root = root.Parent();
\r
61 Collections.reverse(wildcardPrefix);
\r
63 return wildcardPrefix;
\r
66 private static List<AntPatternState> ToAntPatternState(IFileSystem fs, List<Wildcard> wildcardPrefix, boolean caseSensitive, String[] patterns) {
\r
67 List<AntPatternState> result = new ArrayList<AntPatternState>();
\r
68 for (String x : patterns) {
\r
69 result.add(new AntPatternState(ParsePattern(fs, wildcardPrefix, caseSensitive, x)));
\r
74 private static List<Wildcard> ParsePattern(IFileSystem fs, List<Wildcard> rootPrefix, boolean caseSensitive, String pattern) {
\r
75 List<Wildcard> wildcards = AntPatternUtil.ParsePattern(pattern, caseSensitive);
\r
77 if (fs.IsPathAbsolute(pattern))
\r
80 List<Wildcard> result = new ArrayList<Wildcard>();
\r
81 result.addAll(rootPrefix);
\r
82 result.addAll(wildcards);
\r
87 private interface AnyPredicate {
\r
88 boolean matches(AntPatternState.MatchResult r);
\r
91 private static boolean Any(List<AntPatternState> state, String component, AnyPredicate predicate, List<AntPatternState> newState) {
\r
92 boolean any = false;
\r
94 for (int i = 0; i < state.size(); i++) {
\r
95 final AntPatternState.AntPatternStateMatch enter = state.get(i).Enter(component);
\r
96 AntPatternState.MatchResult match = enter.getResult();
\r
97 newState.add(i, enter.getState());
\r
99 if (predicate.matches(match))
\r
106 private static void FindFilesRec(IDirectoryEntry directory, List<FileSystemPath> result, List<AntPatternState> includeState, List<AntPatternState> excludeState) {
\r
107 LOG.debug("Scanning directory: " + directory.Name());
\r
108 for (IFileEntry file : directory.Files()) {
\r
109 List<AntPatternState> newState = new ArrayList<AntPatternState>();
\r
111 if (!Any(includeState, file.Name(), AntPredicateImpl.Predicate(false, AntPatternState.MatchResult.YES), newState))
\r
115 if (Any(excludeState, file.Name(), AntPredicateImpl.Predicate(false, AntPatternState.MatchResult.YES), newState))
\r
118 result.add(file.Path());
\r
121 for (IDirectoryEntry subEntry : directory.Subdirectories()) {
\r
122 String name = subEntry.Name();
\r
124 List<AntPatternState> newIncludeState = new ArrayList<AntPatternState>();
\r
125 if (!Any(includeState, name, AntPredicateImpl.Predicate(true, AntPatternState.MatchResult.NO), newIncludeState))
\r
128 List<AntPatternState> newExcludeState = new ArrayList<AntPatternState>();
\r
129 if (Any(excludeState, name, AntPredicateImpl.Predicate(false, AntPatternState.MatchResult.YES), newExcludeState))
\r
132 FindFilesRec(subEntry, result, newIncludeState, newExcludeState);
\r
136 private static class AntPredicateImpl {
\r
137 private final boolean myNegatiate;
\r
138 private final AntPatternState.MatchResult myResult;
\r
140 private AntPredicateImpl(boolean negatiate, AntPatternState.MatchResult result) {
\r
141 myNegatiate = negatiate;
\r
145 private boolean AnyPredicateImpl(AntPatternState.MatchResult r) {
\r
146 return myNegatiate ? myResult != r : myResult == r;
\r
150 public static AnyPredicate Predicate(boolean not, AntPatternState.MatchResult state) {
\r
151 final AntPredicateImpl antPredicate = new AntPredicateImpl(not, state);
\r
152 return new AnyPredicate() {
\r
153 public boolean matches(AntPatternState.MatchResult r) {
\r
154 return antPredicate.AnyPredicateImpl(r);
\r