//Appends the any xml file/folder nodes onto the folder private void AddXmlNodes(FolderCompareObject folder, int numOfPaths, XmlDocument xmlDoc) { List<XMLCompareObject> xmlObjList = new List<XMLCompareObject>(); List<string> xmlFolderList = new List<string>(); for (int i = 0; i < numOfPaths; i++) { string path = Path.Combine(folder.GetSmartParentPath(i), folder.Name); if (Directory.Exists(path)) { DirectoryInfo dirInfo = new DirectoryInfo(path); FileInfo[] fileList = dirInfo.GetFiles(); DirectoryInfo[] dirInfoList = dirInfo.GetDirectories(); string xmlPath = Path.Combine(path, CommonXMLConstants.MetadataPath); if (!File.Exists(xmlPath)) continue; CommonMethods.LoadXML(ref xmlDoc, xmlPath); xmlObjList = GetAllFilesInXML(xmlDoc); xmlFolderList = GetAllFoldersInXML(xmlDoc); RemoveSimilarFiles(xmlObjList, fileList); RemoveSimilarFolders(xmlFolderList, dirInfoList); } AddFileToChild(xmlObjList, folder, i, numOfPaths); AddFolderToChild(xmlFolderList, folder, i, numOfPaths); xmlObjList.Clear(); xmlFolderList.Clear(); } }
/// <summary> /// Visit <see cref="FolderCompareObject"/> implementation for BuilderVisitor. /// </summary> /// <param name="folder">The <see cref="FolderCompareObject"/> to build and process.</param> /// <param name="numOfPaths">The total number of folders to keep in sync.</param> public void Visit(FolderCompareObject folder, int numOfPaths) { try { RootCompareObject root = folder as RootCompareObject; for (int index = 0; index < numOfPaths; index++) { string path = root == null ? Path.Combine(folder.GetSmartParentPath(index), folder.Name) : root.Paths[index]; DirectoryInfo f = new DirectoryInfo(path); if (f.Exists) { if (_progress != null) { _progress.Message = f.FullName; _progress.Update(); } ProcessFolders(folder, numOfPaths, f, index); ProcessFiles(folder, numOfPaths, f, index); } } } catch (UnauthorizedAccessException e) { ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(e); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.UNKNOWN, "Error retrieving contents of folder due to unauthorized access.")); } catch (PathTooLongException e) { ServiceLocator.GetLogger(ServiceLocator.DEBUG_LOG).Write(e); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.UNKNOWN, "Error retrieving contents of folder due to path being too long.")); } }
/// <summary> /// Visits each folder node and return them and it will update the values either through the meta data /// or the last known state document /// </summary> /// <param name="folder"></param> /// <param name="numOfPaths"></param> public void Visit(FolderCompareObject folder, int numOfPaths) { XmlDocument xmlDoc = new XmlDocument(); PopulateFolderMetaName(folder, numOfPaths); for (int i = 0; i < numOfPaths; i++) { string path = Path.Combine(folder.GetSmartParentPath(i), CommonXMLConstants.MetadataPath); if (!File.Exists(path)) continue; CommonMethods.LoadXML(ref xmlDoc, path); folder = PopulateFolderWithMetaData(xmlDoc, folder, i); } AddXmlNodes(folder, numOfPaths, xmlDoc); }
/// <summary> /// It calls ProcessFolderFinalState method and if either needLastKnownState or the method is true, /// it will call GenerateFolderLastKnownState method to write a last known state document /// </summary> /// <param name="folder"></param> /// <param name="numOfPaths"></param> public void Visit(FolderCompareObject folder, int numOfPaths) { if (folder.Invalid) return; bool needLastKnownState = false; for (int i = 0; i < numOfPaths; i++) { _progress.Message = Path.Combine(folder.GetSmartParentPath(i), folder.Name); needLastKnownState = ProcessFolderFinalState(folder, i) || needLastKnownState; } if (needLastKnownState) GenerateFolderLastKnownState(folder, numOfPaths); _progress.Complete(); }
// Checks the meta data by the folder name , if it exists , set it MetaExists to true. // If not , look up the last known state and populate the values from that document private FolderCompareObject PopulateFolderWithMetaData(XmlDocument xmlDoc, FolderCompareObject folder, int counter) { XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFolder + "[name=" + CommonMethods.ParseXPathString(folder.Name) + "]"); if (node != null) { folder.MetaExists[counter] = true; } else { string path = Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.LastKnownStatePath); if (File.Exists(path)) { XmlDocument lastKnownXmlDoc = new XmlDocument(); CommonMethods.LoadXML(ref lastKnownXmlDoc, path); XmlNode folderNode = lastKnownXmlDoc.SelectSingleNode(CommonXMLConstants.XPathLastKnownState + CommonXMLConstants.XPathFolder + "[name=" + CommonMethods.ParseXPathString(folder.Name) + "]"); if (folderNode != null) { XmlNodeList nodeList = folderNode.ChildNodes; for (int i = 0; i < nodeList.Count; i++) { XmlNode childNode = nodeList[i]; switch (childNode.Name) { case CommonXMLConstants.NodeAction: string action = childNode.InnerText; if (action.Equals("deleted")) folder.LastKnownState[counter] = LastKnownState.Deleted; else folder.LastKnownState[counter] = LastKnownState.Renamed; break; case CommonXMLConstants.NodeLastUpdatedUtc: folder.MetaUpdated[counter] = long.Parse(childNode.InnerText); break; } } } } } return folder; }
// Populate the folder's meta name if it exists private void PopulateFolderMetaName(FolderCompareObject folder, int numOfPaths) { for (int i = 0; i < numOfPaths; i++) { string currMetaData = Path.Combine(Path.Combine(folder.GetSmartParentPath(i), folder.Name), CommonXMLConstants.MetadataPath); if (File.Exists(currMetaData)) { XmlDocument xmlDoc = new XmlDocument(); CommonMethods.LoadXML(ref xmlDoc, currMetaData); XmlNode xmlNode = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + "/name"); if (xmlNode != null) folder.MetaName = xmlNode.InnerText; } } }
private void MoveFolder(FolderCompareObject folder, int numOfPaths, int srcFolderPos) { bool changed = false; for (int i = 0; i < numOfPaths; i++) { if (i != srcFolderPos && folder.Priority[i] != folder.Priority[srcFolderPos]) { string oldFolderName = Path.Combine(folder.GetSmartParentPath(i), folder.Name); string newFolderName = Path.Combine(folder.GetSmartParentPath(i), folder.NewName); string srcFolderName = Path.Combine(folder.GetSmartParentPath(srcFolderPos), folder.NewName); try { if (Directory.Exists(oldFolderName)) { CommonMethods.MoveFolder(oldFolderName, newFolderName); // Rename the old folder to the new name if it exists. folder.FinalState[i] = FinalState.Renamed; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_RENAMED, "Folder renamed from " + oldFolderName + " to " + newFolderName)); } else { CommonMethods.CopyDirectory(srcFolderName, newFolderName); // Copy the directory from the source folder if the old folder does not exist. folder.Exists[i] = true; folder.CreationTimeUtc[i] = Directory.GetCreationTimeUtc(newFolderName).Ticks; folder.FinalState[i] = FinalState.CreatedRenamed; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "Folder copied from " + srcFolderName + " to " + newFolderName)); } changed = true; } catch (MoveFolderException) { folder.FinalState[i] = FinalState.Error; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error renaming folder from " + oldFolderName + " to " + newFolderName)); } catch (CopyFolderException) { folder.FinalState[i] = FinalState.Error; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error copying folder: " + srcFolderName + " to " + newFolderName)); } } else { folder.FinalState[i] = FinalState.Renamed; changed = true; } } folder.FinalState[srcFolderPos] = changed ? FinalState.Renamed : FinalState.Unchanged; // If changed is true, that means at least one file has been affected, set the FinalState to renamed. Otherwise, leave it as Unchanged. }
private void DeleteFolder(FolderCompareObject folder, int numOfPaths, int srcFolderPos) { bool changed = false; for (int i = 0; i < numOfPaths; i++) { if (i != srcFolderPos && folder.Priority[i] != folder.Priority[srcFolderPos]) { string destFolder = Path.Combine(folder.GetSmartParentPath(i), folder.Name); try { if (_syncConfig.ArchiveLimit > 0) { CommonMethods.ArchiveFolder(destFolder, _syncConfig.ArchiveName, _syncConfig.ArchiveLimit); ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ARCHIVED, "Folder archived " + destFolder)); } } catch (ArchiveFolderException) { folder.FinalState[i] = FinalState.Error; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error archiving folder " + destFolder)); } try { if (_syncConfig.Recycle) CommonMethods.DeleteFolderToRecycleBin(destFolder); else CommonMethods.DeleteFolder(destFolder); folder.Exists[i] = false; folder.FinalState[i] = FinalState.Deleted; changed = true; // Set it to true since the change has propaged to at least one folder if (_syncConfig.Recycle) ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "Folder deleted to recycle bin " + destFolder)); else ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_DELETED, "Folder deleted " + destFolder)); } catch (DeleteFolderException) { folder.FinalState[i] = FinalState.Error; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error deleting folder " + destFolder)); } } else { folder.FinalState[i] = folder.MetaExists[i] ? FinalState.Deleted : FinalState.Unchanged; changed = true; // Set it to true since the change has propaged to at least one folder } } folder.FinalState[srcFolderPos] = changed ? FinalState.Deleted : FinalState.Unchanged; // Set the FinalState to deleted if changed is true, otherwise set it as Unchanged. }
private void CreateFolder(FolderCompareObject folder, int numOfPaths, int srcFolderPos) { for (int i = 0; i < numOfPaths; i++) { if (i != srcFolderPos && folder.Priority[i] != folder.Priority[srcFolderPos]) { string folderToCreate = Path.Combine(folder.GetSmartParentPath(i), folder.Name); if (!Directory.Exists(folderToCreate)) { try { CommonMethods.CreateFolder(folderToCreate); // Create the folder since it does not exist folder.Exists[i] = true; // Update the state of the folder folder.CreationTimeUtc[i] = Directory.GetCreationTimeUtc(folderToCreate).Ticks; folder.FinalState[i] = FinalState.Created; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_CREATED, "Folder created " + folderToCreate)); } catch (CreateFolderException) { folder.FinalState[i] = FinalState.Error; ServiceLocator.GetLogger(ServiceLocator.USER_LOG).Write(new LogData(LogEventType.FSCHANGE_ERROR, "Error creating folder " + folderToCreate)); } } } else { folder.FinalState[i] = folder.MetaExists[i] ? FinalState.Unchanged : FinalState.Created; // Set the FinalState to unchanged if the metadata already exists, else set it to created. } } folder.FinalState[srcFolderPos] = folder.MetaExists[srcFolderPos] ? FinalState.Unchanged : FinalState.Created; // Set the FinalState to unchanged if the metadata exists, else set it to created. }
// Checks if the last known state document exists and calls the AppendActionFolderLastKnownState method private void GenerateFolderLastKnownState(FolderCompareObject folder, int numOfPaths) { for (int i = 0; i < numOfPaths; i++) { string parentPath = folder.GetSmartParentPath(i); XmlDocument xmlTodoDoc = new XmlDocument(); string todoPath = Path.Combine(parentPath, CommonXMLConstants.LastKnownStatePath); CommonMethods.CreateLastKnownStateFile(parentPath); CommonMethods.LoadXML(ref xmlTodoDoc, todoPath); CommonMethods.DoFolderLastKnownCleanUp(xmlTodoDoc, folder.Name); AppendActionFolderLastKnownState(xmlTodoDoc, folder, CommonXMLConstants.ActionDeleted); CommonMethods.SaveXML(ref xmlTodoDoc, todoPath); } }
// Deletes a folder node in the last known state file by searching for the name private void DeleteFolderLastKnownState(FolderCompareObject folder, int counter) { string todoXMLPath = Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.LastKnownStatePath); if (!File.Exists(todoXMLPath)) return; XmlDocument todoXMLDoc = new XmlDocument(); CommonMethods.LoadXML(ref todoXMLDoc, todoXMLPath); XmlNode folderNode = todoXMLDoc.SelectSingleNode(CommonXMLConstants.XPathLastKnownState + CommonXMLConstants.XPathFolder + "[name=" + CommonMethods.ParseXPathString(folder.Name) + "]"); if (folderNode != null) folderNode.ParentNode.RemoveChild(folderNode); CommonMethods.SaveXML(ref todoXMLDoc, todoXMLPath); }
// Based on the folder and counter , it will load the xml document and delete the folder node private void DeleteFolderObject(FolderCompareObject folder, int counter) { XmlDocument xmlDoc = new XmlDocument(); string xmlPath = Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath); if (File.Exists(xmlPath)) { CommonMethods.LoadXML(ref xmlDoc, xmlPath); XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFolder + "[name=" + CommonMethods.ParseXPathString(folder.Name) + "]"); if (node == null) return; node.ParentNode.RemoveChild(node); CommonMethods.SaveXML(ref xmlDoc, xmlPath); } }
// Based on the folder and counter , it will load the xml document and rename it private void RenameFolderObject(FolderCompareObject folder, int counter) { if (Directory.Exists(Path.Combine(folder.GetSmartParentPath(counter), folder.Name))) { XmlDocument xmlDoc = new XmlDocument(); string xmlPath = Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath); CommonMethods.LoadXML(ref xmlDoc, xmlPath); XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFolder + "[name=" + CommonMethods.ParseXPathString(folder.Name) + "]"); if (node == null) { CreateFolderObject(folder, counter, true); return; } node.FirstChild.InnerText = folder.NewName; node.LastChild.InnerText = _dateTime.ToString(); CommonMethods.SaveXML(ref xmlDoc, xmlPath); } else { XmlDocument newXmlDoc = new XmlDocument(); string editOldXML = Path.Combine(Path.Combine(folder.GetSmartParentPath(counter), folder.NewName), CommonXMLConstants.MetadataPath); CommonMethods.CreateFileIfNotExist(Path.Combine(folder.GetSmartParentPath(counter), folder.NewName)); CommonMethods.LoadXML(ref newXmlDoc, editOldXML); XmlNode xmlNameNode = newXmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathName); if (xmlNameNode != null) xmlNameNode.InnerText = folder.NewName; CommonMethods.SaveXML(ref newXmlDoc, editOldXML); string parentXML = Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath); XmlDocument parentXmlDoc = new XmlDocument(); CommonMethods.CreateFileIfNotExist(folder.GetSmartParentPath(counter)); CommonMethods.LoadXML(ref parentXmlDoc, parentXML); XmlNode parentXmlFolderNode = parentXmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr + CommonXMLConstants.XPathFolder + "[name=" + CommonMethods.ParseXPathString(folder.Name) + "]"); if (parentXmlFolderNode != null) { parentXmlFolderNode.FirstChild.InnerText = folder.NewName; parentXmlFolderNode.LastChild.InnerText = _dateTime.ToString(); } CommonMethods.SaveXML(ref parentXmlDoc, Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath)); } }
// Based on the folder and counter , it will create a folder node in the meta data private void CreateFolderObject(FolderCompareObject folder, int counter, bool useNewName) { string name = useNewName ? folder.NewName : folder.Name; XmlDocument xmlDoc = new XmlDocument(); string xmlPath = Path.Combine(folder.GetSmartParentPath(counter), CommonXMLConstants.MetadataPath); CommonMethods.CreateFileIfNotExist(folder.GetSmartParentPath(counter)); CommonMethods.LoadXML(ref xmlDoc, xmlPath); CommonMethods.DoFolderCleanUp(xmlDoc, name); XmlText nameText = xmlDoc.CreateTextNode(name); XmlText lastUpdatedUtcText = xmlDoc.CreateTextNode(_dateTime.ToString()); XmlElement nameElement = xmlDoc.CreateElement(CommonXMLConstants.NodeName); XmlElement lastUpdatedElement = xmlDoc.CreateElement(CommonXMLConstants.NodeLastUpdatedUtc); XmlElement folderElement = xmlDoc.CreateElement(CommonXMLConstants.NodeFolder); nameElement.AppendChild(nameText); lastUpdatedElement.AppendChild(lastUpdatedUtcText); folderElement.AppendChild(nameElement); folderElement.AppendChild(lastUpdatedElement); XmlNode node = xmlDoc.SelectSingleNode(CommonXMLConstants.XPathExpr); if (node == null) return; node.AppendChild(folderElement); string subFolderXML = Path.Combine(folder.GetSmartParentPath(counter), name); CommonMethods.CreateFileIfNotExist(subFolderXML); CommonMethods.SaveXML(ref xmlDoc, xmlPath); ModifyFolderName(folder, folder.GetSmartParentPath(counter)); DeleteFolderLastKnownState(folder, counter); }
/// <summary> /// For every FolderCompareObject, check which path has the max priority and then decide /// what sync operation should be approriate for each FolderCompareObject. Once the path of the max /// priority has been set, for every other path which is not the max priority, populate the datagrid /// with by adding a DataRow for each operation that needs to be done. /// </summary> /// <param name="folder"></param> /// <param name="numOfPaths"></param> public void Visit(FolderCompareObject folder, int numOfPaths) { if (folder.Invalid) return; int maxPriorityPos = folder.SourcePosition; if (folder.Priority[maxPriorityPos] > 0) { for (int i = 0; i < numOfPaths; i++) { if (i != maxPriorityPos && folder.Priority[i] != folder.Priority[maxPriorityPos]) { string operation = string.Empty, source = string.Empty, dest = string.Empty, tooltip = string.Empty; DataRow row = SyncData.NewRow(); switch (folder.ChangeType[maxPriorityPos]) { // if the MetaChangeType is of New, Update, Change case MetaChangeType.New: case MetaChangeType.NoChange: case MetaChangeType.Update: source = Path.Combine(folder.GetSmartParentPath(maxPriorityPos), folder.Name); dest = Path.Combine(folder.GetSmartParentPath(i), folder.Name); operation = CopyArrow; tooltip = folder.Exists[i] ? FolderUpdateToolTip : FolderCopyToolTip; break; // if the MetaChangeType is of Delete type case MetaChangeType.Delete: source = Path.Combine(folder.GetSmartParentPath(maxPriorityPos), folder.Name); dest = Path.Combine(folder.GetSmartParentPath(i), folder.Name); operation = DeleteArrow; tooltip = FolderDeleteToolTip; break; // if the MetaChangeType is of Rename type case MetaChangeType.Rename: string oldFolderName = Path.Combine(folder.GetSmartParentPath(i), folder.Name); source = File.Exists(oldFolderName) ? oldFolderName : Path.Combine(folder.GetSmartParentPath(maxPriorityPos), folder.NewName); dest = Path.Combine(folder.GetSmartParentPath(i), folder.NewName); operation = Directory.Exists(oldFolderName) ? RenameArrow : CopyArrow; tooltip = Directory.Exists(oldFolderName) ? FolderRenameToolTip : FolderCopyToolTip; break; } // set all properties of the DataRow which has been decided by the switch case above row[Source] = source; row[Dest] = dest; row[Operation] = operation; row[Tooltip] = tooltip; row[SourceIcon] = FolderIcon; row[DestIcon] = FolderIcon; // Set size and date/time for Folder to none row[SourceLastModifiedDate] = "-"; row[SourceSize] = "-"; row[DestLastModifiedDate] = "-"; row[DestSize] = "-"; _syncData.Rows.Add(row); } } } }