diff --git a/it/compare-generation.ps1 b/it/compare-generation.ps1 index 718a5edee0..f7b6ab89c0 100755 --- a/it/compare-generation.ps1 +++ b/it/compare-generation.ps1 @@ -79,11 +79,11 @@ if ($firstGenerationProcess.ExitCode -ne 0 -or $secondGenerationProcess.ExitCode } # Remove variable output files -Remove-Item (Join-Path -Path $tmpFolder1 -ChildPath "kiota-lock.json") +Remove-Item (Join-Path -Path $tmpFolder1 -ChildPath "*/kiota-lock.json") if (Test-Path (Join-Path -Path $tmpFolder1 -ChildPath ".kiota.log")) { Remove-Item -Force (Join-Path -Path $tmpFolder1 -ChildPath ".kiota.log") } -Remove-Item (Join-Path -Path $tmpFolder2 -ChildPath "kiota-lock.json") +Remove-Item (Join-Path -Path $tmpFolder2 -ChildPath "*/kiota-lock.json") if (Test-Path (Join-Path -Path $tmpFolder2 -ChildPath ".kiota.log")) { Remove-Item -Force (Join-Path -Path $tmpFolder2 -ChildPath ".kiota.log") } diff --git a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs index eac80d47cd..b715c1e466 100644 --- a/src/Kiota.Builder/Configuration/GenerationConfiguration.cs +++ b/src/Kiota.Builder/Configuration/GenerationConfiguration.cs @@ -38,6 +38,7 @@ public ConsumerOperation? Operation public string OpenAPIFilePath { get; set; } = "openapi.yaml"; public string ApiManifestPath { get; set; } = "apimanifest.json"; public string OutputPath { get; set; } = "./output"; + public string ClientOutputPath => Path.Combine(OutputPath, ClientClassName); public string ClientClassName { get; set; } = "ApiClient"; public AccessModifier TypeAccessModifier { get; set; } = AccessModifier.Public; public string ClientNamespaceName { get; set; } = "ApiSdk"; diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 450e392103..ac4f2bee77 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -46,6 +46,7 @@ public partial class KiotaBuilder private readonly ParallelOptions parallelOptions; private readonly HttpClient httpClient; private OpenApiDocument? openApiDocument; + private readonly string outputPath; internal void SetOpenApiDocument(OpenApiDocument document) => openApiDocument = document ?? throw new ArgumentNullException(nameof(document)); public KiotaBuilder(ILogger logger, GenerationConfiguration config, HttpClient client, bool useKiotaConfig = false) @@ -64,19 +65,20 @@ public KiotaBuilder(ILogger logger, GenerationConfiguration config workspaceManagementService = new WorkspaceManagementService(logger, client, useKiotaConfig, workingDirectory); this.useKiotaConfig = useKiotaConfig; openApiDocumentDownloadService = new OpenApiDocumentDownloadService(client, logger); + outputPath = this.config.ClientOutputPath; } private readonly OpenApiDocumentDownloadService openApiDocumentDownloadService; private readonly bool useKiotaConfig; private async Task CleanOutputDirectoryAsync(CancellationToken cancellationToken) { - if (config.CleanOutput && Directory.Exists(config.OutputPath)) + if (config.CleanOutput && Directory.Exists(outputPath)) { - logger.LogInformation("Cleaning output directory {Path}", config.OutputPath); + logger.LogInformation("Cleaning output directory {Path}", outputPath); // not using Directory.Delete on the main directory because it's locked when mapped in a container - foreach (var subDir in Directory.EnumerateDirectories(config.OutputPath)) + foreach (var subDir in Directory.EnumerateDirectories(outputPath)) Directory.Delete(subDir, true); - await workspaceManagementService.BackupStateAsync(config.OutputPath, cancellationToken).ConfigureAwait(false); - foreach (var subFile in Directory.EnumerateFiles(config.OutputPath) + await workspaceManagementService.BackupStateAsync(outputPath, cancellationToken).ConfigureAwait(false); + foreach (var subFile in Directory.EnumerateFiles(outputPath) .Where(static x => !x.EndsWith(FileLogLogger.LogFileName, StringComparison.OrdinalIgnoreCase))) File.Delete(subFile); } @@ -273,7 +275,7 @@ public async Task GenerateClientAsync(CancellationToken cancellationToken) { // Generate public API export sw.Start(); - var fileStream = File.Create(Path.Combine(config.OutputPath, PublicApiExportService.DomExportFileName)); + var fileStream = File.Create(Path.Combine(outputPath, PublicApiExportService.DomExportFileName)); await using (fileStream.ConfigureAwait(false)) { await new PublicApiExportService(config).SerializeDomAsync(fileStream, generatedCode, cancellationToken).ConfigureAwait(false); @@ -301,11 +303,11 @@ private async Task GenerateConsumerAsync(Func GenerateConsumerAsync(Func GetDirectoriesContainingLockFile(string searchDirecto private static async Task GetLockFromDirectoryInternalAsync(string directoryPath, CancellationToken cancellationToken) { var lockFilePath = Path.Combine(directoryPath, LockFileName); + // If the lock file does not exist in the provided directory, try checking in the parent directory. This handles + // clients generated by older versions without this fix + if (!File.Exists(lockFilePath)) + { + // We could use Directory.GetParent, but that involves a syscall which seems unnecessary given '..' is + // supported by File APIs. + // TODO: Check if there are scenarios where using '..' would fail. + lockFilePath = Path.Combine(directoryPath, "..", LockFileName); + } if (File.Exists(lockFilePath)) { #pragma warning disable CA2007 @@ -73,6 +82,7 @@ public Task WriteLockFileAsync(string directoryPath, KiotaLock lockInfo, Cancell private static async Task WriteLockFileInternalAsync(string directoryPath, KiotaLock lockInfo, CancellationToken cancellationToken) { var lockFilePath = Path.Combine(directoryPath, LockFileName); + Directory.CreateDirectory(directoryPath); #pragma warning disable CA2007 await using var fileStream = File.Open(lockFilePath, FileMode.Create); #pragma warning restore CA2007 diff --git a/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs b/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs index 070fc07154..ad59a3c926 100644 --- a/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs +++ b/src/Kiota.Builder/WorkspaceManagement/WorkspaceManagementService.cs @@ -85,7 +85,7 @@ public async Task UpdateStateFromConfigurationAsync(GenerationConfiguration gene { DescriptionHash = descriptionHash ?? string.Empty, }; - await lockManagementService.WriteLockFileAsync(generationConfiguration.OutputPath, configurationLock, cancellationToken).ConfigureAwait(false); + await lockManagementService.WriteLockFileAsync(generationConfiguration.ClientOutputPath, configurationLock, cancellationToken).ConfigureAwait(false); } } public async Task RestoreStateAsync(string outputPath, CancellationToken cancellationToken = default) @@ -139,7 +139,7 @@ public async Task ShouldGenerateAsync(GenerationConfiguration inputConfig, } else { - var existingLock = await lockManagementService.GetLockFromDirectoryAsync(inputConfig.OutputPath, cancellationToken).ConfigureAwait(false); + var existingLock = await lockManagementService.GetLockFromDirectoryAsync(inputConfig.ClientOutputPath, cancellationToken).ConfigureAwait(false); var configurationLock = new KiotaLock(inputConfig) { DescriptionHash = descriptionHash,