private static void ProcessProjectFiles( CurrentOperation operation, string[] conflictPaths, DirectoryInfo folder, Logger logger, string rootFolder ) { var merger = new ProjectMerger( operation, new UserConflictResolver<ProjectReference>( operation, repositoryRootDirectory: rootFolder ), new ReferenceConflictResolver( new UserConflictResolver<Reference>( operation, notResolveOptionText: PackageNotInstalledText, repositoryRootDirectory: rootFolder ) ), new UserConflictResolver<RawItem>( operation, repositoryRootDirectory: rootFolder ), new UserDuplicateResolver<Reference>( operation, notResolveOptionText: PackageNotInstalledText, repositoryRootDirectory: rootFolder ) ); foreach ( var conflict in conflictPaths.Where( p => p.EndsWith( ".csproj" ) || p.EndsWith( ".fsproj" ) || p.EndsWith( ".xproj" )) ) { var fullConflictPath = Path.Combine( folder.FullName, conflict ); logger.Info( $"{LogHelper.Header}{Environment.NewLine}Examining concurrent modification for {fullConflictPath}" ); var baseContent = GitHelper.GetConflictContent( rootFolder, StageLevel.Ancestor, conflict ); var localContent = GitHelper.GetConflictContent( rootFolder, StageLevel.Ours, conflict ); var incomingContent = GitHelper.GetConflictContent( rootFolder, StageLevel.Theirs, conflict ); var conflictFolder = Path.GetDirectoryName( Path.Combine( rootFolder, conflict ) ); if ( conflictFolder == null ) { throw new Exception( "No conflict folder" ); } if ( string.IsNullOrEmpty( localContent ) || string.IsNullOrEmpty( incomingContent ) ) { logger.Log( LogLevel.Info, $"Skipping '{conflict}' - no content on one side" ); continue; } var localDocument = XDocument.Parse( localContent ); var incomingDocument = XDocument.Parse( incomingContent ); var baseDocument = XDocument.Parse( baseContent ?? "<?xml version=\"1.0\" encoding=\"utf - 8\"?><Project/>" ); var resolved = false; try { var projectFolder = Path.Combine( folder.FullName, conflictFolder ); var packagesConfigFilePath = ProjectPackages.GetPackagesConfigFilePath( projectFolder ); var packagesConfig = ProjectPackages.TryLoadPackagesConfig( packagesConfigFilePath ); if ( packagesConfig == null ) { continue; } var packageIndex = new ProjectPackages( projectFolder, NuGetExtensions.FindRelativePathOfPackagesFolder( projectFolder ), packagesConfig ); Item[] items = merger.Merge( conflict, packageIndex, baseDocument, localDocument, incomingDocument ).ToArray(); // Now remove everything we have handled, to check if we are done. ProjectFile.DeleteItems( localDocument ); ProjectFile.DeleteItems( incomingDocument ); ProjectFile.DeleteItems( baseDocument ); ProjectFile.AddItems( baseDocument, items ); ProjectFile.AddItems( localDocument, items ); ProjectFile.AddItems( incomingDocument, items ); XDocument resolvedDocument = null; var localXml = localDocument.ToString(); var incomingXml = incomingDocument.ToString(); var baseXml = baseDocument.ToString(); // Check for any project file changes outside of the references and items. if ( localXml == incomingXml ) { resolvedDocument = localDocument; } else if ( baseXml == localXml ) { resolvedDocument = incomingDocument; } else if ( baseXml == incomingXml ) { resolvedDocument = localDocument; } if ( resolvedDocument != null ) { // We handled all the differences using ( var textWriter = new StreamWriter( fullConflictPath ) ) { SerialisationHelper.WriteXml( resolvedDocument, textWriter ); } using ( var repository = new Repository( rootFolder ) ) { repository.Stage( conflict ); } resolved = true; } } catch ( MergeAbortException ) { logger.Log( LogLevel.Info, $"Project merge aborted for {conflict}" ); continue; } catch ( UserQuitException ) { throw; } catch ( Exception exception ) { logger.Log( LogLevel.Error, exception, $"Project merge failed for {conflict}{Environment.NewLine}{exception}" ); } if ( resolved ) { continue; } string userQuestionText = $"Could not resolve conflict: {conflict}{Environment.NewLine}Would you like to resolve the conflict with the mergetool?"; var userQuestion = new UserQuestion<bool>( userQuestionText, UserQuestion<bool>.YesNoOptions() ); if ( userQuestion.Resolve() ) { using ( var repository = new Repository( rootFolder ) ) { GitHelper.ResolveWithStandardMergetool( repository, fullConflictPath, baseDocument, localDocument, incomingDocument, logger, conflict ); } } } }
private static void ProcessPackagesConfig( CurrentOperation operation, string[] conflictPaths, DirectoryInfo folder, Logger logger, string rootFolder ) { var packagesConfigMerger = new PackagesConfigMerger( operation, new UserConflictResolver<ConfigitPackageReference>( operation, repositoryRootDirectory: rootFolder ) ); foreach ( var conflict in conflictPaths.Where( p => Path.GetFileName( p ) == "packages.config" ) ) { var fullConflictPath = Path.Combine( folder.FullName, conflict ); logger.Info( $"{LogHelper.Header}{Environment.NewLine}Examining concurrent modification for {fullConflictPath}" ); var baseContent = GitHelper.GetConflictContent( rootFolder, StageLevel.Ancestor, conflict ); var localContent = GitHelper.GetConflictContent( rootFolder, StageLevel.Ours, conflict ); var incomingContent = GitHelper.GetConflictContent( rootFolder, StageLevel.Theirs, conflict ); // TODO: Is this correct? if base is not null then we have a deletion of the packages config file if ( string.IsNullOrEmpty( localContent ) || string.IsNullOrEmpty( incomingContent ) ) { logger.Log( LogLevel.Info, $"Skipping '{conflict}' - no content on one side" ); continue; } bool resolved = false; try { var result = packagesConfigMerger.Merge( conflict, baseContent == null ? new ConfigitPackageReference[0]: NuGetExtensions.ReadPackageReferences( baseContent ), NuGetExtensions.ReadPackageReferences( localContent ), NuGetExtensions.ReadPackageReferences( incomingContent ) ).ToArray(); result.Write( fullConflictPath ); using ( var repository = new Repository( rootFolder ) ) { repository.Stage( conflict ); resolved = true; } } catch ( MergeAbortException ) { logger.Log( LogLevel.Info, $"Package merge aborted for {conflict}" ); continue; } catch ( UserQuitException ) { throw; } catch ( Exception exception ) { logger.Log( LogLevel.Error, exception, $"Package merge failed for {conflict}{Environment.NewLine}{exception}" ); } if ( resolved ) { continue; } string userQuestionText = $"Could not resolve conflict: {conflict}{Environment.NewLine}Would you like to resolve the conflict with the mergetool?"; var userQuestion = new UserQuestion<bool>( userQuestionText, UserQuestion<bool>.YesNoOptions() ); if ( !userQuestion.Resolve() ) { continue; } XDocument localDocument = XDocument.Parse( localContent ); XDocument theirDocument = XDocument.Parse( incomingContent ); XDocument baseDocument = baseContent == null ? new XDocument() : XDocument.Parse( baseContent ); using ( var repository = new Repository( rootFolder ) ) { GitHelper.ResolveWithStandardMergetool( repository, fullConflictPath, baseDocument, localDocument, theirDocument, logger, conflict ); } } }