/// <summary> /// Performs an in depth diff by breaking code files into their constituent parts (functions, properties /// etc, so that these elements can be diffed without regard to their ordering. /// </summary> /// <remarks> /// I've put some Thread.Sleep(1) calls in here to ensure that this processing doesn't bring a single core machine /// to its knees. This should ensure that any GUI or other background threads can still get some CPU time, /// as there is not much in here that could cause a context switch. /// </remarks> public bool PerformSuperDiff() { SetupPerformDiff(); try { switch (IntelliMerge) { case IntelliMergeType.CSharp: CSharpParser formatter = new CSharpParser(); try { // Reset the DiffType CurrentDiffResult.DiffType = TypeOfDiff.ExactCopy; if (diffCodeRootMap.PrevGenCodeRoot == null && PrevGenFile.HasContents || ReloadFiles) { formatter.Reset(); string filename = string.IsNullOrEmpty(PrevGenFile.FilePath) ? "Prev Gen File" : PrevGenFile.FilePath; formatter.ParseCode(filename, PrevGenFile.GetContents()); if (formatter.ErrorOccurred) { return(false); } diffCodeRootMap.AddCodeRoot(formatter.CreatedCodeRoot, Version.PrevGen); } // Force a context switch Thread.Sleep(1); if (diffCodeRootMap.NewGenCodeRoot == null && NewGenFile.HasContents || ReloadFiles) { formatter.Reset(); string filename = string.IsNullOrEmpty(NewGenFile.FilePath) ? "New Gen File" : NewGenFile.FilePath; formatter.ParseCode(filename, NewGenFile.GetContents()); if (formatter.ErrorOccurred) { return(false); } diffCodeRootMap.AddCodeRoot(formatter.CreatedCodeRoot, Version.NewGen); } // Force a context switch Thread.Sleep(1); if (diffCodeRootMap.UserCodeRoot == null && UserFile.HasContents || ReloadFiles) { formatter.Reset(); string filename = string.IsNullOrEmpty(UserFile.FilePath) ? "User File" : UserFile.FilePath; formatter.ParseCode(filename, UserFile.GetContents()); if (formatter.ErrorOccurred) { return(false); } diffCodeRootMap.AddCodeRoot(formatter.CreatedCodeRoot, Version.User); } // Force a context switch Thread.Sleep(1); // Set this back to false. If it was true, we have reloaded the files, if it was already false this // does nothing. ReloadFiles = false; } catch (Exception ex) { CurrentDiffResult.ParserWarningDescription = ex.Message; return(false); } finally { if (formatter.ErrorOccurred) { CurrentDiffResult.ParserWarningDescription = formatter.GetFormattedErrors(); } } if (string.IsNullOrEmpty(temporaryManifestFile) == false && manifestFileApplied == false) { CodeRootMapMatchProcessor processor = new CodeRootMapMatchProcessor(); processor.LoadCustomMappings(ManifestConstants.LoadManifestDocument(temporaryManifestFile), diffCodeRootMap, Path.GetFileName(RelativeFilePath)); manifestFileApplied = true; } CurrentDiffResult.DiffType = diffCodeRootMap.Diff(); if (CurrentDiffResult.DiffType != TypeOfDiff.Conflict && CurrentDiffResult.DiffType != TypeOfDiff.Warning) { //mergedFile = new TextFile(CodeRootMap.GetMergedCodeRoot().ToString()); // Slyce.Common.Utility.WriteToFile(newFile, userFile.GetContents()); } break; default: // No SuperDiff available for this type of file (no parser created yet). break; } } catch (Exception ex) { throw new DiffException(ex); } return(true); }
/// <summary> /// The write out process involves the following steps: /// 1. Back up the files currently in the user's project directory. /// 2. Write the template files that are being used to the temporary prevgen directory. /// 3. Write the merged files to the user's project directory. /// 4. Copy those temporary prevgen files over to the user's prevgen directory. /// </summary> /// <param name="helper"></param> /// <param name="tempController"></param> /// <param name="files"></param> /// <param name="projectTree"></param> public void WriteAllFiles(TaskProgressHelper helper, IController tempController, List <IFileInformation> files, ProjectFileTree projectTree, bool overwriteExistingFiles) { controller = tempController; // Calculate which folders need backing up. List <string> directories = new List <string>(); directories.Add(""); // The root folder. foreach (ProjectFileTreeNode node in projectTree.AllNodes) { if (node.IsFolder == false) { continue; } string path = node.Path; if (directories.Contains(path) == false) { directories.Add(path); } } //BackupUtility backupUtility = new BackupUtility(); //string timeString = BackupUtility.GetTimeString(); //foreach(string dir in directories) //{ // backupUtility.CreateBackup( // Path.Combine(controller.CurrentProject.ProjectSettings.ProjectPath, dir), // tempController.CurrentProject.ProjectSettings.ProjectGuid, // Path.GetFileNameWithoutExtension(tempController.CurrentProject.ProjectSettings.TemplateFileName), // Path.Combine(controller.CurrentProject.ProjectSettings.ProjectPath, dir), // timeString); //} foreach (IFileInformation file in files) { if (file.CurrentDiffResult.DiffType == TypeOfDiff.Conflict) { throw new WriteOutException(string.Format("Cannot write out files where a conflict exists! The file {0} has a conflict.", file.RelativeFilePath)); } } foreach (IFileInformation file in files) { WriteSingleFile(file, overwriteExistingFiles); // Write the newly generated file to the temporary directory so we can copy it to the prevgen directory in the // user's project directory. We do this instead of copying the whole newgen directory so we avoid changing the // timestamps on the prevgen files. string prevgenPath = controller.GetTempFilePathForComponent(ComponentKey.Workbench_FileGeneratorOutput); file.WriteNewGenFile(prevgenPath); // TODO: Need to copy the Manifest file over from the temporary prevgen folder to the new one. //CopyAllManifestFiles(controller.GetTempFilePathForComponent(ComponentKey.SlyceMerge_PrevGen), // controller.GetTempFilePathForComponent(ComponentKey.Workbench_FileGeneratorOutput)); if (file.CodeRootMap != null) { CodeRootMapMatchProcessor processor = new CodeRootMapMatchProcessor(); string manifestFilename = Path.Combine(prevgenPath, ManifestConstants.MANIFEST_FILENAME); XmlDocument doc = ManifestConstants.LoadManifestDocument(manifestFilename); processor.SaveCustomMappings(doc, file.CodeRootMap, Path.GetFileName(file.RelativeFilePath)); } } // Copy the temporary files we just created to the user's prevgen directory. CreatePrevGenFiles(); }