protected virtual void OnEvent(SyncEventItem e) { if (Event != null) { Event(this, e); } }
/// <summary> /// Compare Physical Files with Virtual Files /// </summary> /// <param name="pPhysicalRootFolder"></param> internal void Compare(PhysicalRootFolder pPhysicalRootFolder) { //Note : TempPhysicalFile.PhysicalFileFileHash may be empty if the file was locked OnLog("Detect Changes since last Run"); #region Folders #region Matching Folders OnLog("Detecting matching folders start based on path"); //Looking for matching folders (based on path) foreach (VirtualElement VE in this.FlatElementsGetAllFolders()) { PhysicalFolder TempPhysicalFolder = pPhysicalRootFolder._Folders.FirstOrDefault(x => x.RelativeFolderPath.Equals(VE.PathRelative, StringComparison.OrdinalIgnoreCase) && !x.bIdentified); if (TempPhysicalFolder != null) { //The local folder path is still existing TempPhysicalFolder.bIdentified = true; VE.bIdentified = true; } } OnLog("Detecting matching folders end"); #endregion #region Deleted Folders OnLog("Detecting deleted folders start"); //Detect deleted folders ( by default, they are sorted from deepest to nearest) foreach (VirtualElement VE in this.FlatElementsGetAllFolders()) { if (!VE.bIdentified) { var SEI = new SyncEventItem(SyncEventEnum.LocalDelete, VE.ElementId, true, true); OnEvent(SEI); OnLog(String.Format("Local folder is present in the Local DB but missing physically : {0}. LocalDelete Event : {1}", VE.PathRelative, SEI.SyncEventId)); } } OnLog("Detecting deleted folders end"); #endregion #region Detect new folders OnLog("Detecting created folders start"); //Sort folders from nearest to deepest (we create nearest folder first) pPhysicalRootFolder._Folders.Sort((x, y) => x._FullFolderPath.Count(z => z == Path.DirectorySeparatorChar).CompareTo(y._FullFolderPath.Count(z => z == Path.DirectorySeparatorChar))); for (int i = 0; i < pPhysicalRootFolder._Folders.Count; i++) { if (!pPhysicalRootFolder._Folders[i].bIdentified) { pPhysicalRootFolder._Folders[i].bIdentified = true; OnEvent(new SyncEventItem(SyncEventEnum.LocalCreate, pPhysicalRootFolder._Folders[i]._FullFolderPath, true, true)); OnLog(String.Format("Local folder created {0}", pPhysicalRootFolder._Folders[i].RelativeFolderPath)); } } OnLog("Detecting created folders end"); #endregion #endregion #region Files OnLog("Detecting matching files start based on path"); //Looking for matching files (physical vs virtual) foreach (VirtualElement VE in this.FlatElementsGetAllFiles()) { VirtualFile VF = (VirtualFile)VE; //Identify files based on their path PhysicalFile TempPhysicalFile = pPhysicalRootFolder._Files.FirstOrDefault(x => x.FileRelativePath.Equals(VF.PathRelative, StringComparison.OrdinalIgnoreCase) && !x.bIdentified); if (TempPhysicalFile != null) { if (VF.FileHash.Equals(TempPhysicalFile.FileHash, StringComparison.OrdinalIgnoreCase)) { VF.bIdentified = true; TempPhysicalFile.bIdentified = true; } else { //Physical file has changed or is locked //Update Virtual file => the sync process will process it as it has changed VF.bIdentified = true; TempPhysicalFile.bIdentified = true; var SEI = new SyncEventItem(SyncEventEnum.LocalUpdate, VF.ElementId, false, true); OnEvent(SEI); OnLog(String.Format("Local file {0} has been updated -> Event {1}", TempPhysicalFile._FileFullPath, SEI.SyncEventId)); } } } OnLog("Detecting matching files end"); //Note : Impossible to identify renamed + modified files (to do this, we would need to use AlternateDataStreams) OnLog("Performing file comparison start"); //Looking for Virtual files not identified => there is no physical file where there was one => deleted, moved or renamed file foreach (VirtualElement VE in this.FlatElementsGetAllFiles()) { VirtualFile VF = (VirtualFile)VE; if (!VF.bIdentified) { PhysicalFile TempPhysicalFile; OnLog(String.Format("Local file is present in the Local DB but missing physically : {0}", VF.PathRelative)); //Look if the file hasn't been renamed in the same folder TempPhysicalFile = pPhysicalRootFolder._Files.FirstOrDefault(x => x.FileRelativeDirectory.Equals(Tools.GetParentPath(VF.PathRelative), StringComparison.OrdinalIgnoreCase) && x.FileHash.Equals(VF.FileHash, StringComparison.OrdinalIgnoreCase) && !x.bIdentified); if (TempPhysicalFile != null) { OnLog(String.Format("Local file has been renamed to {0}", TempPhysicalFile._FileFullPath)); OnEvent(new SyncEventItem(SyncEventEnum.LocalRename, VF.ElementId, TempPhysicalFile.FileRelativePath, VF.PathRelative, false, true)); VF.bIdentified = true; TempPhysicalFile.bIdentified = true; } else { //Look if the file hasn't been moved to somewhere. File with same name and same hash not already identified TempPhysicalFile = pPhysicalRootFolder._Files.FirstOrDefault(x => Path.GetFileName(x._FileFullPath).Equals(VF.CurrentName, StringComparison.OrdinalIgnoreCase) && x.FileHash.Equals(VF.FileHash, StringComparison.OrdinalIgnoreCase) && !x.bIdentified); if (TempPhysicalFile != null) { OnLog(String.Format("Local file has been moved to {0}", TempPhysicalFile._FileFullPath)); OnEvent(new SyncEventItem(SyncEventEnum.LocalMove, VF.ElementId, TempPhysicalFile.FileRelativePath, VF.PathRelative, false, true)); VF.bIdentified = true; TempPhysicalFile.bIdentified = true; } else { //Note : We don't limit the rename check on same folder only //Look if the file hasn't been renamed based on the hash TempPhysicalFile = pPhysicalRootFolder._Files.FirstOrDefault(x => { return(x.FileHash.Equals(VF.FileHash, StringComparison.OrdinalIgnoreCase) && !x.bIdentified); }); if (TempPhysicalFile != null) { OnLog(String.Format("Local file has been moved and renamed to {0}", TempPhysicalFile._FileFullPath)); OnEvent(new SyncEventItem(SyncEventEnum.LocalMoveAndRename, VF.ElementId, TempPhysicalFile.FileRelativePath, VF.PathRelative, false, true)); VF.bIdentified = true; TempPhysicalFile.bIdentified = true; } else { OnLog(String.Format("Local file has been deleted", VF.PathRelative)); OnEvent(new SyncEventItem(SyncEventEnum.LocalDelete, VF.ElementId, false, true)); VF.bIdentified = true; } } } } } //Looking for Physical files not identified => this file was not in the virtual list //=> New, moved or renamed file for (int i = 0; i < pPhysicalRootFolder._Files.Count; i++) { if (!pPhysicalRootFolder._Files[i].bIdentified) { OnLog(String.Format("New local file {0}", pPhysicalRootFolder._Files[i].FileRelativePath)); OnEvent(new SyncEventItem(SyncEventEnum.LocalCreate, pPhysicalRootFolder._Files[i]._FileFullPath, false, true)); } } OnLog("Performing file comparison end"); #endregion OnLog("Done"); }