SyncFiles method modified to detect conflicts as per #2096
[pithos-ms-client] / trunk / Pithos.Core / Agents / FileSystemWatcherAdapter.cs
index e652f48..54592df 100644 (file)
@@ -1,44 +1,48 @@
-// -----------------------------------------------------------------------\r
-// <copyright file="FileInfoExtensions.cs" company="GRNET">\r
-// Copyright 2011 GRNET S.A. All rights reserved.\r
-// \r
-// Redistribution and use in source and binary forms, with or\r
-// without modification, are permitted provided that the following\r
-// conditions are met:\r
-// \r
-//   1. Redistributions of source code must retain the above\r
-//      copyright notice, this list of conditions and the following\r
-//      disclaimer.\r
-// \r
-//   2. Redistributions in binary form must reproduce the above\r
-//      copyright notice, this list of conditions and the following\r
-//      disclaimer in the documentation and/or other materials\r
-//      provided with the distribution.\r
-// \r
-// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
-// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
-// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
-// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
-// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
-// POSSIBILITY OF SUCH DAMAGE.\r
-// \r
-// The views and conclusions contained in the software and\r
-// documentation are those of the authors and should not be\r
-// interpreted as representing official policies, either expressed\r
-// or implied, of GRNET S.A.\r
-// </copyright>\r
-// -----------------------------------------------------------------------\r
-\r
-\r
+#region\r
+/* -----------------------------------------------------------------------\r
+ * <copyright file="FileSystemWatcherAdapter.cs" company="GRNet">\r
+ * \r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ *   1. Redistributions of source code must retain the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer.\r
+ *\r
+ *   2. Redistributions in binary form must reproduce the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer in the documentation and/or other materials\r
+ *      provided with the distribution.\r
+ *\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ * </copyright>\r
+ * -----------------------------------------------------------------------\r
+ */\r
+#endregion\r
 using System.Diagnostics.Contracts;\r
 using System.IO;\r
 using System.Threading.Tasks;\r
+using Pithos.Interfaces;\r
 \r
 namespace Pithos.Core.Agents\r
 {\r
@@ -103,7 +107,7 @@ namespace Pithos.Core.Agents
             //      as this is actually a MOVE operation\r
             //Deleting by Shift+Delete results in a delete event for each file followed by the delete of the folder itself\r
             _cachedDeletedFullPath = e.FullPath;\r
-\r
+            \r
             //TODO: This requires synchronization of the _cachedDeletedFullPath field\r
             //TODO: This creates a new task for each file even though we can cancel any existing tasks if a new event arrives\r
             //Maybe, use a timer instead of a task\r
@@ -196,8 +200,30 @@ namespace Pithos.Core.Agents
                 //If the actual action is a Move, raise a Move event instead of the actual event\r
                 var newDirectory = Path.GetDirectoryName(e.FullPath);\r
                 var oldDirectory = Path.GetDirectoryName(_cachedDeletedFullPath);\r
+\r
                 if (Moved != null)\r
+                {\r
                     Moved(sender, new MovedEventArgs(newDirectory, newName, oldDirectory, oldName));\r
+                    //If the moved item is a dictionary, we need to raise a change event for each child item\r
+                    //When a directory is moved within the same volume, Windows raises events only for the directory object,\r
+                    //not its children. This happens because the move actually changes a single directory entry. It doesn't\r
+                    //affect the entries of the children.\r
+                    var directory = new DirectoryInfo(e.FullPath);\r
+                    if (directory.Exists)\r
+                    {\r
+                        foreach (var child in directory.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))\r
+                        {\r
+                            var newChildDirectory = Path.GetDirectoryName(child.FullName);\r
+\r
+                            var relativePath=child.AsRelativeTo(newDirectory);\r
+                            var relativeFolder = Path.GetDirectoryName(relativePath);\r
+                            var oldChildDirectory = Path.Combine(oldDirectory, relativeFolder);\r
+                            Moved(sender,new MovedEventArgs(newChildDirectory,child.Name,oldChildDirectory,child.Name));\r
+                        }\r
+                    }\r
+\r
+                }\r
+\r
             }\r
             finally\r
             {\r
@@ -220,8 +246,12 @@ namespace Pithos.Core.Agents
             var deletedFileName = Path.GetFileName(_cachedDeletedFullPath);\r
             var deletedFileDirectory = Path.GetDirectoryName(_cachedDeletedFullPath);\r
 \r
-            if (Deleted!=null)\r
-                Deleted(sender, new FileSystemEventArgs(WatcherChangeTypes.Deleted, deletedFileDirectory, deletedFileName));\r
+            //Only a single file Delete event is raised when moving a file to the Recycle Bin, as this is actually a MOVE operation\r
+            //In this case we need to raise the proper events for all child objects of the deleted directory.\r
+            //UNFORTUNATELY, this can't be detected here, eg. by retrieving the child objects, because they are already deleted\r
+            //This should be done at a higher level, eg by checking the stored state\r
+            if (Deleted != null)            \r
+                Deleted(sender,new FileSystemEventArgs(WatcherChangeTypes.Deleted, deletedFileDirectory, deletedFileName));\r
 \r
             _cachedDeletedFullPath = null;\r
         }\r