2 // DirectoryScanner.cs: Class used by BuildItem.
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections.Generic;
34 namespace Microsoft.Build.BuildEngine {
35 internal class DirectoryScanner {
37 DirectoryInfo baseDirectory;
40 string[] matchedFilenames;
42 public DirectoryScanner ()
48 Dictionary <string, bool> excludedItems;
49 List <string> includedItems;
50 string[] splitInclude, splitExclude;
53 throw new ArgumentNullException ("Includes");
55 throw new ArgumentNullException ("Excludes");
56 if (baseDirectory == null)
57 throw new ArgumentNullException ("BaseDirectory");
59 excludedItems = new Dictionary <string, bool> ();
60 includedItems = new List <string> ();
62 splitInclude = includes.Split (';');
63 splitExclude = excludes.Split (';');
65 if (excludes != String.Empty) {
66 foreach (string si in splitExclude) {
67 ProcessExclude (si, excludedItems);
70 if (includes != String.Empty) {
71 foreach (string si in splitInclude) {
72 ProcessInclude (si, excludedItems, includedItems);
76 matchedFilenames = includedItems.ToArray ();
79 private void ProcessInclude (string name, Dictionary <string, bool> excludedItems, List <string> includedItems)
81 string[] separatedPath;
84 if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
85 if (!excludedItems.ContainsKey (Path.GetFullPath(name)))
86 includedItems.Add (name);
88 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
89 separatedPath = name.Split (Path.DirectorySeparatorChar);
91 separatedPath = name.Split (Path.AltDirectorySeparatorChar);
93 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
95 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
96 foreach (FileInfo fi in fileInfo)
97 if (!excludedItems.ContainsKey (fi.FullName))
98 includedItems.Add (fi.FullName);
102 private void ProcessExclude (string name, Dictionary <string, bool> excludedItems)
104 string[] separatedPath;
107 if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
108 if (!excludedItems.ContainsKey (Path.GetFullPath (name)))
109 excludedItems.Add (Path.GetFullPath (name), true);
111 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
112 separatedPath = name.Split (Path.DirectorySeparatorChar);
114 separatedPath = name.Split (Path.AltDirectorySeparatorChar);
116 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
118 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
119 foreach (FileInfo fi in fileInfo)
120 if (!excludedItems.ContainsKey (fi.FullName))
121 excludedItems.Add (fi.FullName, true);
125 private FileInfo[] ParseIncludeExclude (string[] input, int ptr, DirectoryInfo directory)
127 if (input.Length > 1 && ptr == 0 && input [0] == String.Empty)
129 if (input.Length == ptr + 1) {
131 fi = directory.GetFiles (input [ptr]);
136 List <FileInfo> fileInfos = new List <FileInfo> ();
137 if (input [ptr] == ".") {
138 di = new DirectoryInfo [1];
140 } else if (input [ptr] == "..") {
141 di = new DirectoryInfo [1];
142 di [0] = directory.Parent;
143 } else if (input[ptr] == "**")
145 // Read this directory and all subdirectories recursive
146 Stack<DirectoryInfo> currentDirectories = new Stack<DirectoryInfo>();
147 currentDirectories.Push(directory);
148 List<DirectoryInfo> allDirectories = new List<DirectoryInfo>();
150 while (currentDirectories.Count > 0)
152 DirectoryInfo current = currentDirectories.Pop();
153 allDirectories.Add (current);
154 foreach (DirectoryInfo dir in current.GetDirectories())
156 currentDirectories.Push(dir);
160 // No further directories shall be read
161 di = allDirectories.ToArray();
163 di = directory.GetDirectories (input [ptr]);
164 foreach (DirectoryInfo info in di) {
165 fi = ParseIncludeExclude (input, ptr + 1, info);
166 foreach (FileInfo file in fi)
167 fileInfos.Add (file);
169 fi = new FileInfo [fileInfos.Count];
171 foreach (FileInfo file in fileInfos)
177 public DirectoryInfo BaseDirectory {
178 get { return baseDirectory; }
179 set { baseDirectory = value; }
182 public string Includes {
183 get { return includes; }
184 set { includes = value; }
187 public string Excludes {
188 get { return excludes; }
189 set { excludes = value; }
192 public string[] MatchedFilenames {
193 get { return matchedFilenames; }