private static bool SynchronizeFolders(List <string> resxFiles1Paths, List <string> resxFiles2Paths, string folderBackupPath, ref string log) { bool hasErrors = false; bool hasConflicts = false; CustomTraceLog customTraceLog = new CustomTraceLog(log); #region prepare backup folder //make structure: //..folderBackupPath\2012.12.12_12:12:00\1\*.resx //..folderBackupPath\2012.12.12_12:12:00\2\*.resx //..folderBackupPath\2012.12.12_12:12:00\log.txt customTraceLog.AddLine("Creating backup folder structure in:'" + folderBackupPath + "' ..."); folderBackupPath = folderBackupPath.TrimEnd('\\'); if (!Directory.Exists(folderBackupPath)) { Directory.CreateDirectory(folderBackupPath); } DateTime now = DateTime.UtcNow; string moment = string.Format("{0}.{1:00}.{2:00}._{3:00}-{4:00}-{5:00}", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); string folderBackupPathWithMoment = folderBackupPath + "\\" + moment; Directory.CreateDirectory(folderBackupPathWithMoment); string folderBackupPathWithMomentForFolder1 = folderBackupPathWithMoment + "\\1"; Directory.CreateDirectory(folderBackupPathWithMomentForFolder1); string folderBackupPathWithMomentForFolder2 = folderBackupPathWithMoment + "\\2"; Directory.CreateDirectory(folderBackupPathWithMomentForFolder2); foreach (var resxFiles1Path in resxFiles1Paths) { string fileName = Path.GetFileName(resxFiles1Path); string destFilePath = Path.Combine(folderBackupPathWithMomentForFolder1, fileName); File.Copy(resxFiles1Path, destFilePath); } foreach (var resxFiles2Path in resxFiles2Paths) { string fileName = Path.GetFileName(resxFiles2Path); string destFilePath = Path.Combine(folderBackupPathWithMomentForFolder2, fileName); File.Copy(resxFiles2Path, destFilePath); } customTraceLog.AddLine("Finished creating backup folder structure."); #endregion #region find pairs and log non paired customTraceLog.AddLine("Finding pairs in two folders..."); List <KeyValuePair <string, string> > pairs = new List <KeyValuePair <string, string> >(); for (int f1 = 0; f1 < resxFiles1Paths.Count; f1++) { string pairFile = resxFiles2Paths.SingleOrDefault(f => string.Compare(Path.GetFileName(resxFiles1Paths[f1]), Path.GetFileName(f), StringComparison.OrdinalIgnoreCase) == 0); if (pairFile == null) { hasErrors = true; customTraceLog.AddLine(string.Format("Error: No pair file for: {0}", resxFiles1Paths[f1])); } else { pairs.Add(new KeyValuePair <string, string>(resxFiles1Paths[f1], pairFile)); } } for (int f2 = 0; f2 < resxFiles1Paths.Count; f2++) { bool allreadyPaired = pairs.Where(p => string.Compare(resxFiles2Paths[f2], p.Value, StringComparison.OrdinalIgnoreCase) == 0).Count() > 0; if (!allreadyPaired) { hasErrors = true; customTraceLog.AddLine(string.Format("Error: No pair file for: {0}", resxFiles2Paths[f2])); } } customTraceLog.AddLine("Finished finding pairs in two folders."); #endregion foreach (var pair in pairs) { bool hasC; bool hasE = Synchronizer.SynchronizeResxFiles(pair.Key, pair.Value, ref customTraceLog, now, out hasC); hasErrors = hasErrors || hasE; hasConflicts = hasConflicts || hasC; } customTraceLog.AddLine(string.Format("Finished. Has errors:{0}, Has conflicts:{1}", hasErrors, hasConflicts)); log = customTraceLog.ToString(); string logFilePath = Path.Combine(folderBackupPathWithMoment, "Log.txt"); File.WriteAllText(logFilePath, log); return(hasErrors); }
private static void SynchronizeResxFilesInner(CustomTraceLog customTraceLog, ref XmlDocument sourceXmlDoc, ref XmlDocument destinationXmlDoc, DateTime now, ref bool hasErrors, ref bool hasConflicts, ref bool leftFileChanged, ref bool rightFileChanged, ref List <string> processedKeys) { XmlNodeList nodes = sourceXmlDoc.SelectNodes("/root/data"); for (int n = nodes.Count - 1; n >= 0; n--) { XmlNode node = nodes[n]; ResxItem sourceResxItem = new ResxItem(); sourceResxItem.Key = node.Attributes["name"].Value; sourceResxItem.Value = node["value"].InnerText; sourceResxItem.Comment = node["comment"] == null ? null : node["comment"].InnerText; sourceResxItem.MoveTimestampsFromCommentToProperties(); //sourceResxItem.Comment!=null && sourceResxItem.Comment.Contains("min pass size") if (!processedKeys.Contains(sourceResxItem.Key)) { processedKeys.Add(sourceResxItem.Key); ResxItem destinationResxItem = null; XmlNode pairInDestinationXml = destinationXmlDoc.SelectSingleNode("/root/data[@name='" + node.Attributes["name"].Value + "']"); if (pairInDestinationXml != null) { destinationResxItem = new ResxItem(); destinationResxItem.Key = pairInDestinationXml.Attributes["name"].Value; destinationResxItem.Value = pairInDestinationXml["value"].InnerText; destinationResxItem.Comment = pairInDestinationXml["comment"] == null ? null : pairInDestinationXml["comment"].InnerText; destinationResxItem.MoveTimestampsFromCommentToProperties(); } bool hasC; CustomTraceLog tLog = new CustomTraceLog(string.Empty); bool hasE = SynchronizeResxItems(ref sourceResxItem, ref destinationResxItem, tLog, now, out hasC); hasErrors = hasErrors || hasE; hasConflicts = hasConflicts || hasC; if (sourceResxItem.Changed || destinationResxItem.Changed || hasE || hasC) { customTraceLog.ExtendLastLine(node.Attributes["name"].Value.PadRight(80, ' ') + ": "); customTraceLog.ExtendLastLine(tLog.ToString()); } if (sourceResxItem.Changed) { if (sourceResxItem.Deleted) { sourceResxItem.DeleteNode(ref sourceXmlDoc, sourceResxItem.Key); leftFileChanged = true; } else { sourceResxItem.ReapplyDatesToComment(); sourceResxItem.CopyToNode(ref sourceXmlDoc, ref node); leftFileChanged = true; } } if (destinationResxItem.Changed) { if (destinationResxItem.Deleted) { destinationResxItem.DeleteNode(ref destinationXmlDoc, destinationResxItem.Key); rightFileChanged = true; } else { destinationResxItem.ReapplyDatesToComment(); destinationResxItem.CopyToNode(ref destinationXmlDoc, ref pairInDestinationXml); rightFileChanged = true; } } if (sourceResxItem.Changed || destinationResxItem.Changed) { customTraceLog.AddLine(""); } } } }