public SlnMergeMergeContext(SolutionFile solutionFile, SolutionFile overlaySolutionFile, SolutionFile mergedSolutionFile, SlnMergeSettings settings, ISlnMergeLogger logger) { SolutionFile = solutionFile; OverlaySolutionFile = overlaySolutionFile; MergedSolutionFile = mergedSolutionFile; Settings = settings; Logger = logger; }
public static bool TryMerge(string solutionFilePath, string solutionFileContent, ISlnMergeLogger logger, out string resultSolutionContent) { try { // Load SlnMerge settings from .mergesttings var slnFileDirectory = Path.GetDirectoryName(solutionFilePath); var slnMergeSettings = new SlnMergeSettings(); var slnMergeSettingsPath = Path.Combine(slnFileDirectory, Path.GetFileName(solutionFilePath) + ".mergesettings"); if (File.Exists(slnMergeSettingsPath)) { logger.Debug($"Using SlnMerge Settings: {slnMergeSettingsPath}"); slnMergeSettings = SlnMergeSettings.FromFile(slnMergeSettingsPath); } else { logger.Debug($"SlnMerge Settings (Not found): {slnMergeSettingsPath}"); } if (slnMergeSettings.Disabled) { logger.Debug("SlnMerge is currently disabled."); resultSolutionContent = solutionFileContent; return(true); } // Determine a overlay solution path. var overlaySolutionFilePath = Path.Combine(slnFileDirectory, Path.GetFileNameWithoutExtension(solutionFilePath) + ".Merge.sln"); if (!string.IsNullOrEmpty(slnMergeSettings.MergeTargetSolution)) { overlaySolutionFilePath = NormalizePath(Path.Combine(slnFileDirectory, slnMergeSettings.MergeTargetSolution)); } if (!File.Exists(overlaySolutionFilePath)) { logger.Warn($"Cannot load the solution file to merge. skipped: {overlaySolutionFilePath}"); resultSolutionContent = null; return(false); } // Merge the solutions. var solutionFile = SolutionFile.Parse(solutionFilePath, solutionFileContent); var overlaySolutionFile = SolutionFile.ParseFromFile(overlaySolutionFilePath); var mergedSolutionFile = Merge(solutionFile, overlaySolutionFile, slnMergeSettings, logger); // Get file content of the merged solution. resultSolutionContent = mergedSolutionFile.ToFileContent(); } catch (Exception e) { logger.Error("Failed to merge the solutions", e); resultSolutionContent = null; return(false); } return(true); }
public static SolutionFile Merge(SolutionFile solutionFile, SolutionFile overlaySolutionFile, SlnMergeSettings settings, ISlnMergeLogger logger) { logger.Debug($"Merge solution: Base={solutionFile.Path}; Overlay={overlaySolutionFile.Path}"); var ctx = new SlnMergeMergeContext(solutionFile, overlaySolutionFile, solutionFile.Clone(), settings, logger); MergeProjects(ctx); MergeGlobalSections(ctx); ModifySolutionFolders(ctx); return(ctx.MergedSolutionFile); }
private static void ModifySolutionFolders(SolutionFile solutionFile, SlnMergeSettings settings, ISlnMergeLogger logger) { if (settings.NestedProjects == null || settings.NestedProjects.Length == 0) { return; } // Build a solution folder tree. var solutionTree = BuildSolutionFlatTree(solutionFile); // Create a NestedProject section in the solution if it does not exist. if (!solutionFile.Global.Sections.TryGetValue(("NestedProjects", "preSolution"), out var section)) { section = new SolutionGlobalSection(solutionFile.Global, "NestedProjects", "preSolution"); solutionFile.Global.Sections.Add((section.Category, section.Value), section); } // Prepare to add nested projects. var nestedProjects = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (var nestedProject in settings.NestedProjects) { var nestedProjectGuid = default(string); var nestedProjectFolderGuid = default(string); // Find a target project if (string.IsNullOrEmpty(nestedProject.ProjectName)) { // by GUID nestedProjectGuid = nestedProject.ProjectGuid; } else { // by Name var proj = solutionFile.Projects.Values.FirstOrDefault(x => x.Name == nestedProject.ProjectName); if (proj != null) { nestedProjectGuid = proj.Guid; } } // Find a solution folder if (string.IsNullOrEmpty(nestedProject.FolderPath)) { // by GUID nestedProjectFolderGuid = nestedProject.FolderGuid; } else { // by Path if (solutionTree.TryGetValue(nestedProject.FolderPath, out var folderNode)) { if (!folderNode.IsFolder) { throw new Exception($"Path '{nestedProject.FolderPath}' is not a Solution Folder."); } nestedProjectFolderGuid = folderNode.Project.Guid; } else { // The target Solution Folder does not exist. make the Solution Folders. var pathParts = nestedProject.FolderPath.Split('/', '\\'); for (var i = 0; i < pathParts.Length; i++) { var path = string.Join("/", pathParts.Take(i + 1)); var parentPath = string.Join("/", pathParts.Take(i)); if (solutionTree.TryGetValue(path, out var folderNode2)) { // A solution tree node already exists. if (!folderNode2.IsFolder) { throw new Exception($"Path '{path}' is not a Solution Folder."); } } else { // Create a new solution folder. var newFolder = new SolutionProject(solutionFile, typeGuid: GuidProjectTypeFolder, guid: Guid.NewGuid().ToString("B").ToUpper(), name: pathParts[i], path: pathParts[i] ); solutionFile.Projects.Add(newFolder.Guid, newFolder); // If the solution folder has a parent folder, add the created folder as a child immediately. if (!string.IsNullOrEmpty(parentPath)) { section.Values[newFolder.Guid] = solutionTree[parentPath].Project.Guid; } // Rebuild the solution tree. solutionTree = BuildSolutionFlatTree(solutionFile); nestedProjectFolderGuid = newFolder.Guid; } } } } // Verify GUIDs / Paths if (nestedProjectGuid == null) { throw new Exception($"Project '{nestedProject.ProjectName}' does not exists in the solution."); } if (nestedProjectFolderGuid == null) { throw new Exception($"Solution Folder '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } if (!solutionFile.Projects.ContainsKey(nestedProjectGuid)) { throw new Exception($"Project '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } if (!solutionFile.Projects.ContainsKey(nestedProjectFolderGuid)) { throw new Exception($"Solution Folder '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } nestedProjects.Add(nestedProjectGuid, nestedProjectFolderGuid); } // Add nested projects. foreach (var keyValue in nestedProjects) { section.Values[keyValue.Key] = keyValue.Value; } }
private static void MergeGlobalSections(SolutionFile solutionFile, SolutionFile overlaySolutionFile, SlnMergeSettings settings, ISlnMergeLogger logger) { foreach (var sectionKeyValue in overlaySolutionFile.Global.Sections) { if (solutionFile.Global.Sections.TryGetValue(sectionKeyValue.Key, out var targetSection)) { foreach (var keyValue in sectionKeyValue.Value.Values) { targetSection.Values[keyValue.Key] = keyValue.Value; } targetSection.Children.AddRange(sectionKeyValue.Value.Children); } else { solutionFile.Global.Sections.Add(sectionKeyValue.Key, sectionKeyValue.Value); } } }
private static void MergeProjects(SolutionFile solutionFile, SolutionFile overlaySolutionFile, SlnMergeSettings settings, ISlnMergeLogger logger) { foreach (var project in overlaySolutionFile.Projects) { if (!solutionFile.Projects.ContainsKey(project.Key)) { if (!project.Value.IsFolder) { var overlayProjectPathAbsolute = NormalizePath(Path.Combine(Path.GetDirectoryName(overlaySolutionFile.Path), project.Value.Path)); project.Value.Path = MakeRelative(solutionFile.Path, overlayProjectPathAbsolute); } solutionFile.Projects.Add(project.Key, project.Value); } else { // A project already exists. } } }