Some more fixes wrt child-indexables. Namely, fix proper handling of child indexables...
[beagle.git] / beagled / FileSystemQueryable / FileNameFilter.cs
blob89fb87a74baf01763596ba05224aabb2aeb612d4
1 //
2 // FileNameFilter.cs
3 //
4 // Copyright (C) 2004, 2005 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.Text.RegularExpressions;
30 using System.IO;
32 using Beagle.Util;
34 namespace Beagle.Daemon.FileSystemQueryable {
36 public class FileNameFilter {
38 private FileSystemQueryable queryable;
40 private static bool Debug = false;
42 // All user defined excludes, used for determining deltas
43 // when the configuration is reloaded.
44 private ArrayList excludes = new ArrayList ();
46 // User defined paths to exclude
47 private ArrayList exclude_paths = new ArrayList ();
49 // User defined exclude patterns
50 private ArrayList exclude_patterns = new ArrayList ();
52 // Our default exclude patterns
53 private ArrayList exclude_patterns_default = new ArrayList ();
55 /////////////////////////////////////////////////////////////
57 // Setup our default exclude patterns.
59 private void SetupDefaultPatternsToIgnore ()
61 // FIXME: This probably shouldn't be hard-wired. Or should it?
62 AddDefaultPatternToIgnore (new string [] {
63 ".*",
64 "*~",
65 "#*#",
66 "*.o",
67 "*.a",
68 "*.S",
69 "*.la",
70 "*.lo",
71 "*.loT",
72 "*.so",
73 "*.exe",
74 "*.dll",
75 "*.mdb",
76 "*.com",
77 "*.csproj",
78 "*.dsp",
79 "*.dsw",
80 "*.m4",
81 "*.pc",
82 "*.pc.in",
83 "*.in.in",
84 "*.omf",
85 "*.aux",
86 "*.tmp",
87 "autom4te.cache",
88 "po",
89 "aclocal",
90 "Makefile",
91 "Makefile.am",
92 "Makefile.in",
93 "CVS",
94 "SCCS",
95 // Garbage generated by the autotools
96 "conftest",
97 "confdefs.h",
98 "conftest.*",
99 "confstat*",
100 "/conf[0-9]+.sh/",
101 "/conf[0-9]+.file/"
105 private void AddDefaultPatternToIgnore (IEnumerable patterns)
107 foreach (string pattern in patterns)
108 exclude_patterns_default.Add (new ExcludeItem (ExcludeType.Pattern, pattern));
111 /////////////////////////////////////////////////////////////
113 private void AddExclude (ExcludeItem exclude)
115 if (Debug)
116 Logger.Log.Debug ("FileNameFilter: Adding ExcludeItem (value={0}, type={1})", exclude.Value, exclude.Type);
118 switch (exclude.Type) {
119 case ExcludeType.Path:
120 exclude_paths.Add (exclude);
121 queryable.RemoveDirectory (exclude.Value);
122 break;
123 case ExcludeType.Pattern:
124 exclude_patterns.Add (exclude);
125 break;
126 default:
127 return;
130 excludes.Add (exclude);
133 private bool RemoveExclude (ExcludeItem exclude)
135 if (Debug)
136 Logger.Log.Debug ("FileNameFilter: Removing ExcludeItem (value={0}, type={1})", exclude.Value, exclude.Type);
138 switch (exclude.Type) {
139 case ExcludeType.Path:
140 exclude_paths.Remove (exclude);
141 break;
142 case ExcludeType.Pattern:
143 exclude_patterns.Remove (exclude);
144 break;
145 default:
146 return false;
149 excludes.Remove (exclude);
151 return true;
154 /////////////////////////////////////////////////////////////
156 public FileNameFilter (FileSystemQueryable queryable)
158 this.queryable = queryable;
160 SetupDefaultPatternsToIgnore ();
161 LoadConfiguration ();
164 /////////////////////////////////////////////////////////////
166 // Load data from configuration. Intersect deltas to the currently active excludes and
167 // implement any changes upon notification.
169 private void LoadConfiguration ()
171 foreach (ExcludeItem exclude in Conf.Indexing.Excludes)
172 AddExclude (exclude);
174 Conf.Subscribe (typeof (Conf.IndexingConfig), OnConfigurationChanged);
177 private void OnConfigurationChanged (Conf.Section section)
179 ArrayList exclude_paths_removed = new ArrayList ();
181 IList excludes_wanted = Conf.Indexing.Excludes;
182 IList excludes_to_add, excludes_to_remove;
183 bool clear_fs_state = false;
185 ArrayFu.IntersectListChanges (excludes_wanted,
186 excludes,
187 out excludes_to_add,
188 out excludes_to_remove);
190 // Process any excludes we think we should remove
191 foreach (ExcludeItem exclude in excludes_to_remove) {
192 if (exclude.Type == ExcludeType.Pattern)
193 clear_fs_state = true;
194 else if (exclude.Type == ExcludeType.Path)
195 exclude_paths_removed.Add (exclude.Value);
196 RemoveExclude (exclude);
199 // Process any excludes we found to be new
200 foreach (ExcludeItem exclude in excludes_to_add)
201 AddExclude (exclude);
203 // If an exclude pattern is removed, we need to recrawl everything
204 // so that we can index those files which were previously ignored.
205 if (clear_fs_state)
206 queryable.RecrawlEverything ();
208 // Make sure we re-crawl the paths we used to ignored but
209 // no longer do.
210 foreach (string path in exclude_paths_removed)
211 queryable.Recrawl (path);
214 /////////////////////////////////////////////////////////////
216 // Try to match any of our current excludes to determine if
217 // we should ignore a file/directory or not.
219 public bool Ignore (DirectoryModel parent, string name, bool is_directory)
221 if (Debug)
222 Logger.Log.Debug ("*** Ignore Check (parent={0}, name={1}, is_directory={2})", (parent != null) ? parent.FullName : null, name, is_directory);
224 // If parent is null, we have a root. But it might not be
225 // active anymore so we need to check if it's still in the list.
226 if (parent == null && queryable.Roots.Contains (name)) {
227 if (Debug)
228 Logger.Log.Debug ("*** Ignore Check Passed");
229 return false;
232 string path;
233 if (parent != null)
234 path = Path.Combine (parent.FullName, name);
235 else
236 path = name;
238 // Exclude paths
239 foreach (ExcludeItem exclude in exclude_paths)
240 if (exclude.IsMatch (path))
241 return true;
243 // Exclude patterns
244 foreach (ExcludeItem exclude in exclude_patterns)
245 if (exclude.IsMatch (name))
246 return true;
248 // Default exclude patterns
249 foreach (ExcludeItem exclude in exclude_patterns_default)
250 if (exclude.IsMatch (name))
251 return true;
253 if (parent == null) {
254 if (Debug)
255 Logger.Log.Debug ("*** Parent is null (name={0}, is_directory={1}", name, is_directory);
256 return false;
259 // This is kind of a hack, but if parent.Parent is null, we need to pass
260 // the full path of the directory as second argument to Ignore to allow
261 // us to do the root check.
262 return Ignore (parent.Parent, (parent.Parent == null) ? parent.FullName : parent.Name, true);