4 // Copyright (C) 2004, 2005 Novell, Inc.
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.
28 using System
.Collections
;
29 using System
.Text
.RegularExpressions
;
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 [] {
95 // Garbage generated by the autotools
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
)
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
);
123 case ExcludeType
.Pattern
:
124 exclude_patterns
.Add (exclude
);
130 excludes
.Add (exclude
);
133 private bool RemoveExclude (ExcludeItem exclude
)
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
);
142 case ExcludeType
.Pattern
:
143 exclude_patterns
.Remove (exclude
);
149 excludes
.Remove (exclude
);
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
,
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.
206 queryable
.RecrawlEverything ();
208 // Make sure we re-crawl the paths we used to ignored but
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
)
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
)) {
228 Logger
.Log
.Debug ("*** Ignore Check Passed");
234 path
= Path
.Combine (parent
.FullName
, name
);
239 foreach (ExcludeItem exclude
in exclude_paths
)
240 if (exclude
.IsMatch (path
))
244 foreach (ExcludeItem exclude
in exclude_patterns
)
245 if (exclude
.IsMatch (name
))
248 // Default exclude patterns
249 foreach (ExcludeItem exclude
in exclude_patterns_default
)
250 if (exclude
.IsMatch (name
))
253 if (parent
== null) {
255 Logger
.Log
.Debug ("*** Parent is null (name={0}, is_directory={1}", name
, is_directory
);
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);