Revision 139ac1e8 trunk/Pithos.Core/Agents/FileSystemWatcherAdapter.cs

b/trunk/Pithos.Core/Agents/FileSystemWatcherAdapter.cs
42 42
using System.Diagnostics.Contracts;
43 43
using System.IO;
44 44
using System.Threading.Tasks;
45
using Pithos.Interfaces;
45 46

  
46 47
namespace Pithos.Core.Agents
47 48
{
......
106 107
            //      as this is actually a MOVE operation
107 108
            //Deleting by Shift+Delete results in a delete event for each file followed by the delete of the folder itself
108 109
            _cachedDeletedFullPath = e.FullPath;
109

  
110
            
110 111
            //TODO: This requires synchronization of the _cachedDeletedFullPath field
111 112
            //TODO: This creates a new task for each file even though we can cancel any existing tasks if a new event arrives
112 113
            //Maybe, use a timer instead of a task
......
199 200
                //If the actual action is a Move, raise a Move event instead of the actual event
200 201
                var newDirectory = Path.GetDirectoryName(e.FullPath);
201 202
                var oldDirectory = Path.GetDirectoryName(_cachedDeletedFullPath);
203

  
202 204
                if (Moved != null)
205
                {
203 206
                    Moved(sender, new MovedEventArgs(newDirectory, newName, oldDirectory, oldName));
207
                    //If the moved item is a dictionary, we need to raise a change event for each child item
208
                    //When a directory is moved within the same volume, Windows raises events only for the directory object,
209
                    //not its children. This happens because the move actually changes a single directory entry. It doesn't
210
                    //affect the entries of the children.
211
                    var directory = new DirectoryInfo(e.FullPath);
212
                    if (directory.Exists)
213
                    {
214
                        foreach (var child in directory.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
215
                        {
216
                            var newChildDirectory = Path.GetDirectoryName(child.FullName);
217

  
218
                            var relativePath=child.AsRelativeTo(newDirectory);
219
                            var relativeFolder = Path.GetDirectoryName(relativePath);
220
                            var oldChildDirectory = Path.Combine(oldDirectory, relativeFolder);
221
                            Moved(sender,new MovedEventArgs(newChildDirectory,child.Name,oldChildDirectory,child.Name));
222
                        }
223
                    }
224

  
225
                }
226

  
204 227
            }
205 228
            finally
206 229
            {
......
223 246
            var deletedFileName = Path.GetFileName(_cachedDeletedFullPath);
224 247
            var deletedFileDirectory = Path.GetDirectoryName(_cachedDeletedFullPath);
225 248

  
226
            if (Deleted!=null)
227
                Deleted(sender, new FileSystemEventArgs(WatcherChangeTypes.Deleted, deletedFileDirectory, deletedFileName));
249
            //Only a single file Delete event is raised when moving a file to the Recycle Bin, as this is actually a MOVE operation
250
            //In this case we need to raise the proper events for all child objects of the deleted directory.
251
            //UNFORTUNATELY, this can't be detected here, eg. by retrieving the child objects, because they are already deleted
252
            //This should be done at a higher level, eg by checking the stored state
253
            if (Deleted != null)            
254
                Deleted(sender,new FileSystemEventArgs(WatcherChangeTypes.Deleted, deletedFileDirectory, deletedFileName));
228 255

  
229 256
            _cachedDeletedFullPath = null;
230 257
        }

Also available in: Unified diff