internal void PerformDiffOfFile(DiffFile diffFile, ref bool fileNeedsToBeCounted) { // Don't process files that had errors during generation for (int errFileCounter = 0; errFileCounter < GenerationErrors.Count; errFileCounter++) { if (Slyce.Common.Utility.StringsAreEqual(diffFile.RelativePath, GenerationErrors[errFileCounter].FileName, false)) { //continue; return; } } if (UniqueFilesForCount[diffFile.RelativePath] != null && (bool)UniqueFilesForCount[diffFile.RelativePath] == false) { fileNeedsToBeCounted = true; UniqueFilesForCount[diffFile.RelativePath] = true; } else { fileNeedsToBeCounted = false; } if (diffFile.Path.IndexOf(".aaz") > 0 || diffFile.HasParseError) { //continue; return; } if (FileBeingProcessed != null) { FileBeingProcessed(diffFile.Path); } // Perform a 3-way diff on the file string parentFile = Path.Combine(PreviousGenerationFolder, diffFile.RelativePath); string userFile = Path.Combine(Controller.Instance.ProjectSettings.ProjectPath, diffFile.RelativePath); string templateFile = Path.Combine(Controller.Instance.GetTempFilePathForComponent(ComponentKey.WorkbenchFileGenerator), diffFile.RelativePath); string mergedFile = Path.Combine(StagingFolder, diffFile.RelativePath + ".merged"); if(CheckFilesForModifications(diffFile.RelativePath) == false) { RaiseDiffFinishedEvent(diffFile.Name, TypeOfDiff.ExactCopy); return; } diffFile.FilePathTemplate = templateFile; diffFile.FilePathUser = userFile; diffFile.FilePathPrevGen = parentFile; if (File.Exists(mergedFile)) { bool mergeComplete = true; // Binary files are never in an unknown state, they are all or nothing. // Text files need to be checked. if (diffFile.IsText) { using (TextReader tr = new StreamReader(mergedFile)) { string line; //int lineCounter = 0; while ((line = tr.ReadLine()) != null && mergeComplete) { int pipeIndex = line.IndexOf("|"); int backColor = int.Parse(line.Substring(0, pipeIndex)); if (backColor != -1 && backColor != 0) { mergeComplete = false; } //lineCounter++; } } } if (mergeComplete) { diffFile.DiffType = TypeOfDiff.Warning; } else { diffFile.DiffType = TypeOfDiff.Conflict; } } else { if (diffFile.IsText) { if (File.Exists(parentFile) && File.Exists(userFile) && File.Exists(templateFile)) { // Perform 3-way diff string fileBodyParent = IOUtility.GetTextFileBody(parentFile); string fileBodyUser = IOUtility.GetTextFileBody(userFile); string fileBodyGenerated = IOUtility.GetTextFileBody(templateFile); string mergedText; slyceMerge = SlyceMerge.Perform3wayDiff(fileBodyUser, fileBodyParent, fileBodyGenerated, out mergedText); diffFile.DiffType = slyceMerge.DiffType; string newFile = ""; if (slyceMerge.DiffType != TypeOfDiff.Conflict) { switch (slyceMerge.DiffType) { case TypeOfDiff.ExactCopy: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newFile); break; case TypeOfDiff.TemplateChangeOnly: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newFile); break; case TypeOfDiff.UserAndTemplateChange: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; if (!Directory.Exists(Path.GetDirectoryName(newFile))) { Directory.CreateDirectory(Path.GetDirectoryName(newFile)); } Slyce.Common.Utility.WriteToFile(newFile, mergedText); break; case TypeOfDiff.UserChangeOnly: newFile = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newFile); break; case TypeOfDiff.Warning: throw new Exception("Oops"); } } } else if (File.Exists(parentFile) && File.Exists(userFile) && !File.Exists(templateFile)) { // No template file, just use the user file diffFile.DiffType = TypeOfDiff.UserChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (File.Exists(parentFile) && !File.Exists(userFile) && File.Exists(templateFile)) { // No user file, just use the template file diffFile.DiffType = TypeOfDiff.TemplateChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else if (!File.Exists(parentFile) && File.Exists(userFile) && File.Exists(templateFile)) { // No parent file, make sure the user merges the template and user files SlyceMerge.LineSpan[] userLines; SlyceMerge.LineSpan[] templateLines; string combinedText; diffFile.DiffType = SlyceMerge.PerformTwoWayDiff(false, IOUtility.GetTextFileBody(userFile), IOUtility.GetTextFileBody(templateFile), out userLines, out templateLines, out combinedText); if (diffFile.DiffType == TypeOfDiff.ExactCopy) { string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else { throw new NotImplementedException("This scenario has not been handled yet. Please contact [email protected] with: PerformDiffOfFolder(PrevGen file doesn't exist, and TypeOfDiff = " + diffFile.DiffType + ")"); } //diffFile.DiffType = SlyceMerge.TypeOfDiff.Conflict; // TODO: Work out what should be done in this instance //throw new Exception("TODO: determine course of action, what should be copied to staging folder."); //string newPath = templateFile.Replace(ProjectFolder, StagingFolder) + ".copy"; //Utility.FileCopy(templateFile, newPath); } else if (File.Exists(parentFile) && !File.Exists(userFile) && !File.Exists(templateFile)) { // TODO: It looks like the file was deleted by the user, AND it was removed from the template, so therefore the // user doesn't want this file anymore. Get user to confirm? string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(parentFile, newPath); } else if (!File.Exists(parentFile) && !File.Exists(userFile) && File.Exists(templateFile)) { string newPath = templateFile.Replace(Controller.Instance.GetTempFilePathForComponent(ComponentKey.WorkbenchFileGenerator), StagingFolder) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else if (!File.Exists(parentFile) && File.Exists(userFile) && !File.Exists(templateFile)) { // TODO: Do we really need to go to the effort of copying etc, because it only exists in the user folder, // so if we take no action it will still exist there - that should be fine ;-) string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else { // TODO: Shouldn't really be a warning... diffFile.DiffType = TypeOfDiff.Warning; throw new Exception(string.Format("TODO: determine course of action, what should be copied to staging folder, because no file exists: \n{0}\n{1}\n{2}", parentFile, userFile, templateFile)); } } else // Binary file { string crcParent = File.Exists(parentFile) ? Slyce.Common.Utility.GetCheckSumOfFile(parentFile) : ""; string crcTemplate = File.Exists(templateFile) ? Slyce.Common.Utility.GetCheckSumOfFile(templateFile) : ""; string crcUser = File.Exists(userFile) ? Slyce.Common.Utility.GetCheckSumOfFile(userFile) : ""; diffFile.MD5Parent = crcParent; diffFile.MD5Template = crcTemplate; diffFile.MD5User = crcUser; // TODO: perform CheckSum of binary file if (!string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && !string.IsNullOrEmpty(crcUser)) { if (crcParent == crcUser && crcUser == crcTemplate) { diffFile.DiffType = TypeOfDiff.ExactCopy; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (crcParent == crcUser && crcParent != crcTemplate) { diffFile.DiffType = TypeOfDiff.TemplateChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (crcParent != crcUser && crcParent == crcTemplate) { diffFile.DiffType = TypeOfDiff.UserChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (crcParent != crcUser && crcUser == crcTemplate) { diffFile.DiffType = TypeOfDiff.UserAndTemplateChange; } } else if (string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && !string.IsNullOrEmpty(crcUser)) { diffFile.DiffType = TypeOfDiff.Conflict; } else if (!string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && string.IsNullOrEmpty(crcUser)) { diffFile.DiffType = TypeOfDiff.TemplateChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else if (!string.IsNullOrEmpty(crcParent) && string.IsNullOrEmpty(crcTemplate) && !string.IsNullOrEmpty(crcUser)) { diffFile.DiffType = TypeOfDiff.UserChangeOnly; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(userFile, newPath); } else if (string.IsNullOrEmpty(crcParent) && !string.IsNullOrEmpty(crcTemplate) && string.IsNullOrEmpty(crcUser)) { // This is a new file that has been generated diffFile.DiffType = TypeOfDiff.ExactCopy; string newPath = Path.Combine(StagingFolder, diffFile.RelativePath) + ".copy"; Slyce.Common.Utility.FileCopy(templateFile, newPath); } else { throw new NotImplementedException("Not coded yet. Seems like only one version of binary file exists. Probably just need to copy as-is."); } } } if (diffFile.DiffType != TypeOfDiff.ExactCopy) { // Only perform the costly SuperDiff if it is not an exact copy //ArchAngel.IntelliMerge.DiffItems.DiffFile diffFile = diffFile; PerformSuperDiff(ref diffFile); } if (fileNeedsToBeCounted) { switch (diffFile.DiffType) { case TypeOfDiff.Conflict: m_numConflicts++; break; case TypeOfDiff.ExactCopy: m_numExactCopy++; break; case TypeOfDiff.TemplateChangeOnly: case TypeOfDiff.UserAndTemplateChange: case TypeOfDiff.UserChangeOnly: case TypeOfDiff.Warning: m_numResolvable++; break; default: throw new NotImplementedException("Not coded yet"); } RaiseDiffFinishedEvent(diffFile.Name, diffFile.DiffType); } Slyce.Common.Utility.DeleteFileBrute(templateFile + ".prevgen.md5"); Slyce.Common.Utility.DeleteFileBrute(templateFile + ".user.md5"); if (diffFile.DiffType == TypeOfDiff.ExactCopy) { // Store the MD5 hashes of the files we just diff'd, so we don't do them again. if(File.Exists(parentFile)) Slyce.Common.Utility.CreateMD5HashFileForTextFile(parentFile, templateFile + ".prevgen.md5"); if(File.Exists(userFile)) Slyce.Common.Utility.CreateMD5HashFileForTextFile(userFile, templateFile + ".user.md5"); } }
internal void SetDiffType(TypeOfDiff diffType) { DiffType = SlyceMerge.CombineDiffTypes(DiffType, diffType); }