diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e715171e6..8811159f84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Emit `[GeneratedCode]` attribute for C# types. [#4907](https://github.com/microsoft/kiota/issues/4907) - Fixes error property disambiguation when the property has the same name as class [#4893](https://github.com/microsoft/kiota/issues/) - Fixes missing imports for `UntypedNode` for method parameter and return value scenarios. [#4925](https://github.com/microsoft/kiota/issues/4925) +- Normalize path separators in lock and workspace files to use `/` as the path separator. [#4228](https://github.com/microsoft/kiota/issues/4228) ## [1.15.0] - 2024-06-06 diff --git a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs index 7200211e63..1f9de43628 100644 --- a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs +++ b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs @@ -197,7 +197,7 @@ private string NormalizeDescriptionLocation(string targetDirectory) !OpenAPIFilePath.StartsWith("http", StringComparison.OrdinalIgnoreCase) && Path.IsPathRooted(OpenAPIFilePath) && Path.GetFullPath(OpenAPIFilePath).StartsWith(Path.GetFullPath(targetDirectory), StringComparison.Ordinal)) - return "./" + Path.GetRelativePath(targetDirectory, OpenAPIFilePath); + return "./" + Path.GetRelativePath(targetDirectory, OpenAPIFilePath).NormalizePathSeparators(); return OpenAPIFilePath; } public bool IsPluginConfiguration => PluginTypes.Count != 0; diff --git a/src/Kiota.Builder/Extensions/StringExtensions.cs b/src/Kiota.Builder/Extensions/StringExtensions.cs index 1eb95f5f9d..1c66ed83d3 100644 --- a/src/Kiota.Builder/Extensions/StringExtensions.cs +++ b/src/Kiota.Builder/Extensions/StringExtensions.cs @@ -299,4 +299,10 @@ public static string GetFileExtension(this string path) if (string.IsNullOrEmpty(path)) return string.Empty; return Path.GetExtension(path).TrimStart('.'); } + public static string NormalizePathSeparators(this string path) + { + if (string.IsNullOrEmpty(path)) return string.Empty; + if (Path.DirectorySeparatorChar != '/') return path.Replace(Path.DirectorySeparatorChar, '/'); + return path; + } } diff --git a/src/Kiota.Builder/Lock/LockManagementService.cs b/src/Kiota.Builder/Lock/LockManagementService.cs index db4a17c30d..b35c2ba12f 100644 --- a/src/Kiota.Builder/Lock/LockManagementService.cs +++ b/src/Kiota.Builder/Lock/LockManagementService.cs @@ -7,6 +7,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Kiota.Builder.Extensions; namespace Kiota.Builder.Lock; @@ -83,7 +84,7 @@ private static string GetRelativeDescriptionPath(string descriptionPath, string { if (IsDescriptionLocal(descriptionPath) && Path.GetDirectoryName(lockFilePath) is string lockFileDirectoryPath) - return Path.GetRelativePath(lockFileDirectoryPath, descriptionPath); + return Path.GetRelativePath(lockFileDirectoryPath, descriptionPath).NormalizePathSeparators(); return descriptionPath; } /// diff --git a/src/Kiota.Builder/WorkspaceManagement/BaseApiConsumerConfiguration.cs b/src/Kiota.Builder/WorkspaceManagement/BaseApiConsumerConfiguration.cs index 5bdbf36388..823b95cea8 100644 --- a/src/Kiota.Builder/WorkspaceManagement/BaseApiConsumerConfiguration.cs +++ b/src/Kiota.Builder/WorkspaceManagement/BaseApiConsumerConfiguration.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using Kiota.Builder.Configuration; +using Kiota.Builder.Extensions; using Microsoft.OpenApi.ApiManifest; namespace Kiota.Builder.WorkspaceManagement; @@ -41,12 +42,12 @@ private protected BaseApiConsumerConfiguration(GenerationConfiguration config) public void NormalizeOutputPath(string targetDirectory) { if (Path.IsPathRooted(OutputPath)) - OutputPath = "./" + Path.GetRelativePath(targetDirectory, OutputPath); + OutputPath = "./" + Path.GetRelativePath(targetDirectory, OutputPath).NormalizePathSeparators(); } public void NormalizeDescriptionLocation(string targetDirectory) { if (Path.IsPathRooted(DescriptionLocation) && Path.GetFullPath(DescriptionLocation).StartsWith(Path.GetFullPath(targetDirectory), StringComparison.Ordinal) && !DescriptionLocation.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - DescriptionLocation = "./" + Path.GetRelativePath(targetDirectory, DescriptionLocation); + DescriptionLocation = "./" + Path.GetRelativePath(targetDirectory, DescriptionLocation).NormalizePathSeparators(); } protected void CloneBase(BaseApiConsumerConfiguration target) { diff --git a/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs b/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs index d98f548cc8..dd5ac7e8d5 100644 --- a/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs +++ b/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs @@ -331,7 +331,7 @@ public async Task> MigrateFromLockFileAsync(string clientNam } var generationConfiguration = new GenerationConfiguration(); lockInfo.UpdateGenerationConfigurationFromLock(generationConfiguration); - generationConfiguration.OutputPath = "./" + Path.GetRelativePath(WorkingDirectory, lockFileDirectory); + generationConfiguration.OutputPath = "./" + Path.GetRelativePath(WorkingDirectory, lockFileDirectory).NormalizePathSeparators(); if (!string.IsNullOrEmpty(clientName)) { generationConfiguration.ClientClassName = clientName; diff --git a/tests/Kiota.Builder.Tests/Lock/LockManagementServiceTests.cs b/tests/Kiota.Builder.Tests/Lock/LockManagementServiceTests.cs index a00aafe3ff..f88c264885 100644 --- a/tests/Kiota.Builder.Tests/Lock/LockManagementServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Lock/LockManagementServiceTests.cs @@ -50,7 +50,7 @@ public async Task UsesRelativePaths() var outputDirectory = Path.Combine(tmpPath, "output"); Directory.CreateDirectory(outputDirectory); await lockManagementService.WriteLockFileAsync(outputDirectory, lockFile); - Assert.Equal($"..{Path.DirectorySeparatorChar}information{Path.DirectorySeparatorChar}description.yml", lockFile.DescriptionLocation, StringComparer.OrdinalIgnoreCase); + Assert.Equal("../information/description.yml", lockFile.DescriptionLocation, StringComparer.OrdinalIgnoreCase); } [Fact] public async Task DeletesALock()