2006-03-11 Marek Sieradzki <marek.sieradzki@gmail.com>
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / DirectoryScanner.cs
1 //
2 // DirectoryScanner.cs: Class used by BuildItem.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 // 
7 // (C) 2005 Marek Sieradzki
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27
28 #if NET_2_0
29
30 using System;
31 using System.Collections;
32 using System.IO;
33
34 namespace Microsoft.Build.BuildEngine {
35         internal class DirectoryScanner {
36                 
37                 DirectoryInfo   baseDirectory;
38                 string          includes;
39                 string          excludes;
40                 string[]        matchedFilenames;
41                 
42                 public DirectoryScanner ()
43                 {
44                 }
45                 
46                 public void Scan ()
47                 {
48                         Hashtable excludedItems;
49                         ArrayList includedItems;
50                         string[] splittedInclude, splittedExclude;
51                         
52                         if (includes == null)
53                                 throw new ArgumentNullException ("Includes");
54                         if (excludes == null)
55                                 throw new ArgumentNullException ("Excludes");
56                         if (baseDirectory == null)
57                                 throw new ArgumentNullException ("BaseDirectory");
58                         
59                         excludedItems = new Hashtable ();
60                         includedItems = new ArrayList ();
61                         
62                         splittedInclude = includes.Split (';');
63                         splittedExclude = excludes.Split (';');
64                         
65                         if (excludes != String.Empty) {
66                                 foreach (string si in splittedExclude) {
67                                         ProcessExclude (si, excludedItems);
68                                 }
69                         }
70                         foreach (string si in splittedInclude) {
71                                 ProcessInclude (si, excludedItems, includedItems);
72                         }
73
74                         matchedFilenames = (string[])includedItems.ToArray (typeof (string));
75                 }
76                 
77                 private void ProcessInclude (string name, Hashtable excludedItems, ArrayList includedItems)
78                 {
79                         string[] separatedPath;
80                         FileInfo[] fileInfo;
81                         
82                         if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
83                                 if (!excludedItems.Contains (Path.GetFullPath(name)))
84                                         includedItems.Add (name);
85                         } else {
86                                 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
87                                         separatedPath = name.Split (Path.DirectorySeparatorChar);
88                                 } else {
89                                         separatedPath = name.Split (Path.AltDirectorySeparatorChar);
90                                 }
91                                 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
92                                         return;
93                                 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
94                                 foreach (FileInfo fi in fileInfo)
95                                         if (!excludedItems.Contains (fi.FullName))
96                                                 includedItems.Add (fi.FullName);
97                         }
98                 }
99                 
100                 private void ProcessExclude (string name, Hashtable excludedItems)
101                 {
102                         string[] separatedPath;
103                         FileInfo[] fileInfo;
104                         
105                         if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
106                                 if (!excludedItems.Contains (Path.GetFullPath (name)))
107                                         excludedItems.Add (Path.GetFullPath (name), null);
108                         } else {
109                                 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
110                                         separatedPath = name.Split (Path.DirectorySeparatorChar);
111                                 } else {
112                                         separatedPath = name.Split (Path.AltDirectorySeparatorChar);
113                                 }
114                                 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
115                                         return;
116                                 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
117                                 foreach (FileInfo fi in fileInfo)
118                                         if (!excludedItems.Contains (fi.FullName))
119                                                 excludedItems.Add (fi.FullName, null);
120                         }
121                 }
122                 
123                 private FileInfo[] ParseIncludeExclude (string[] input, int ptr, DirectoryInfo directory)
124                 {
125                         if (input.Length > 1 && ptr == 0 && input [0] == String.Empty)
126                                 ptr++;
127                         if (input.Length == ptr + 1) {
128                                 FileInfo[] fi;
129                                 fi = directory.GetFiles (input [ptr]);
130                                 return fi;
131                         } else {
132                                 DirectoryInfo[] di;
133                                 FileInfo[] fi;
134                                 ArrayList fileInfos = new ArrayList ();
135                                 if (input [ptr] == ".") {
136                                         di = new DirectoryInfo [1];
137                                         di [0] = directory;
138                                 } else if (input [ptr] == "..") {
139                                         di = new DirectoryInfo [1];
140                                         di [0] = directory.Parent;
141                                 } else
142                                         di = directory.GetDirectories (input [ptr]);
143                                 foreach (DirectoryInfo info in di) {
144                                         fi = ParseIncludeExclude (input, ptr + 1, info);
145                                         foreach (FileInfo file in fi)
146                                                 fileInfos.Add (file);
147                                 }
148                                 fi = new FileInfo [fileInfos.Count];
149                                 int i = 0;
150                                 foreach (FileInfo file in fileInfos)
151                                         fi [i++] = file;
152                                 return fi;
153                         }
154                 }
155                 
156                 public DirectoryInfo BaseDirectory {
157                         get { return baseDirectory; }
158                         set { baseDirectory = value; }
159                 }
160                 
161                 public string Includes {
162                         get { return includes; }
163                         set { includes = value; }
164                 }
165                 
166                 public string Excludes {
167                         get { return excludes; }
168                         set { excludes = value; }
169                 }
170                 
171                 public string[] MatchedFilenames {
172                         get { return matchedFilenames; }
173                 }
174                 
175         }
176 }
177
178 #endif