Move from xbuild into mcs
[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 using System;
29 using System.Collections;
30 using System.IO;
31
32 namespace Microsoft.Build.BuildEngine {
33         internal class DirectoryScanner {
34                 
35                 DirectoryInfo   baseDirectory;
36                 string          includes;
37                 string          excludes;
38                 string[]        matchedFilenames;
39                 
40                 public DirectoryScanner ()
41                 {
42                 }
43                 
44                 public void Scan ()
45                 {
46                         Hashtable temporaryItems;
47                         string[] splittedInclude, splittedExclude;
48                 
49                         if (includes == null)
50                                 throw new ArgumentNullException ("Includes");
51                         if (excludes == null)
52                                 throw new ArgumentNullException ("Excludes");
53                         if (baseDirectory == null)
54                                 throw new ArgumentNullException ("BaseDirectory");
55                         
56                         temporaryItems = new Hashtable ();
57                         
58                         splittedInclude = includes.Split (';');
59                         splittedExclude = excludes.Split (';');
60                         
61                         foreach (string si in splittedInclude) {
62                                 ProcessInclude (si, temporaryItems);
63                         }
64                         if (excludes != String.Empty) {
65                                 foreach (string si in splittedExclude) {
66                                         ProcessExclude (si, temporaryItems);
67                                 }
68                         }
69                         
70                         matchedFilenames = new string [temporaryItems.Count];
71                         int i = 0;
72                         foreach (DictionaryEntry de in temporaryItems)
73                                 matchedFilenames [i++] = (string) de.Value; 
74                 }
75                 
76                 private void ProcessInclude (string name, Hashtable temporaryItems)
77                 {
78                         string[] separatedPath;
79                         FileInfo[] fileInfo;
80                         
81                         if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1)
82                                 temporaryItems.Add (Path.GetFullPath (name), name);
83                         else {
84                                 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
85                                         separatedPath = name.Split (Path.DirectorySeparatorChar);
86                                 } else {
87                                         separatedPath = name.Split (Path.AltDirectorySeparatorChar);
88                                 }
89                                 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
90                                         return;
91                                 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
92                                 foreach (FileInfo fi in fileInfo)
93                                         temporaryItems.Add (fi.FullName, fi.FullName);
94                         }
95                 }
96                 
97                 private void ProcessExclude (string name, Hashtable temporaryItems)
98                 {
99                         string[] separatedPath;
100                         FileInfo[] fileInfo;
101                         
102                         if (name.IndexOf ('?') == -1 && name.IndexOf ('*') == -1) {
103                                 if (temporaryItems.Contains (Path.GetFullPath (name)))
104                                         temporaryItems.Remove (Path.GetFullPath (name));
105                         } else {
106                                 if (name.Split (Path.DirectorySeparatorChar).Length > name.Split (Path.AltDirectorySeparatorChar).Length) {
107                                         separatedPath = name.Split (Path.DirectorySeparatorChar);
108                                 } else {
109                                         separatedPath = name.Split (Path.AltDirectorySeparatorChar);
110                                 }
111                                 if (separatedPath.Length == 1 && separatedPath [0] == String.Empty)
112                                         return;
113                                 fileInfo = ParseIncludeExclude (separatedPath, 0, baseDirectory);
114                                 foreach (FileInfo fi in fileInfo)
115                                         if (temporaryItems.Contains (fi.FullName))
116                                                 temporaryItems.Remove (fi.FullName);
117                         }
118                 }
119                 
120                 private FileInfo[] ParseIncludeExclude (string[] input, int ptr, DirectoryInfo directory)
121                 {
122                         if (input.Length > 1 && ptr == 0 && input [0] == String.Empty)
123                                 ptr++;
124                         if (input.Length == ptr + 1) {
125                                 FileInfo[] fi;
126                                 fi = directory.GetFiles (input [ptr]);
127                                 return fi;
128                         } else {
129                                 DirectoryInfo[] di;
130                                 FileInfo[] fi;
131                                 ArrayList fileInfos = new ArrayList ();
132                                 if (input [ptr] == ".") {
133                                         di = new DirectoryInfo [1];
134                                         di [0] = directory;
135                                 } else if (input [ptr] == "..") {
136                                         di = new DirectoryInfo [1];
137                                         di [0] = directory.Parent;
138                                 } else
139                                         di = directory.GetDirectories (input [ptr]);
140                                 foreach (DirectoryInfo info in di) {
141                                         fi = ParseIncludeExclude (input, ptr + 1, info);
142                                         foreach (FileInfo file in fi)
143                                                 fileInfos.Add (file);
144                                 }
145                                 fi = new FileInfo [fileInfos.Count];
146                                 int i = 0;
147                                 foreach (FileInfo file in fileInfos)
148                                         fi [i++] = file;
149                                 return fi;
150                         }
151                 }
152                 
153                 public DirectoryInfo BaseDirectory {
154                         get { return baseDirectory; }
155                         set { baseDirectory = value; }
156                 }
157                 
158                 public string Includes {
159                         get { return includes; }
160                         set { includes = value; }
161                 }
162                 
163                 public string Excludes {
164                         get { return excludes; }
165                         set { excludes = value; }
166                 }
167                 
168                 public string[] MatchedFilenames {
169                         get { return matchedFilenames; }
170                 }
171                 
172         }
173 }