diff --git a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManager.cs b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManager.cs index cf40b2825..53458d308 100644 --- a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManager.cs +++ b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManager.cs @@ -77,6 +77,50 @@ public Task RemoveAsync(bool global, string extension, CancellationToken c return Task.FromResult(false); } + + public async Task UpdateAsync(bool global, string extension, CancellationToken cancellationToken) + { + if (String.IsNullOrEmpty(extension)) + { + throw new ArgumentNullException(nameof(extension)); + } + + (var extensionId, var extensionVersion) = ParseExtensionReference(extension); + + var cacheFolder = this.GetCacheFolder(global); + + // Get installed extension versions: + var extensionFolder = Path.Combine(cacheFolder, extensionId); + var extensionNugetVersion = NuGetVersion.Parse(extensionVersion); + + // Maybe the extension is not installed at all. + if (Directory.Exists(extensionFolder)) + { + foreach (var existingExtensionVersionFolder in Directory.GetDirectories(extensionFolder)) + { + cancellationToken.ThrowIfCancellationRequested(); + + // Remove only older versions, so parse the version: + var existingExtensionVersionFolderName = Path.GetFileName(existingExtensionVersionFolder); + if (!NuGetVersion.TryParse(existingExtensionVersionFolderName, out var existingExtensionNugetVersion)) + { + throw new ArgumentException($"Invalid extension version in {existingExtensionVersionFolder}: {existingExtensionVersionFolderName}"); + } + + if (existingExtensionNugetVersion.Version < extensionNugetVersion.Version) + { + // Remove old version: + // TODO: reuse extension removal message. + this.Messaging.Write("Removing old version: " + existingExtensionVersionFolder); + + Directory.Delete(existingExtensionVersionFolder, true); + } + } + } + // Now update extension: + return await this.AddAsync(global, extension, cancellationToken); + } + public Task> ListAsync(bool global, string extension, CancellationToken cancellationToken) { var found = new List(); diff --git a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs index a1059e834..f1d9838ea 100644 --- a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs +++ b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs @@ -20,6 +20,9 @@ internal class ExtensionCacheManagerCommand : BaseCommandLineCommand private enum CacheSubcommand { Add, + + Update, + Remove, List } @@ -52,6 +55,7 @@ public override CommandLineHelp GetCommandLineHelp() Commands = new[] { new CommandLineHelpCommand("add", "Add extension to the cache."), + new CommandLineHelpCommand("update", "Update extension in the cache. If the extension is not installed, it is the same as 'add'."), new CommandLineHelpCommand("list", "List extensions in the cache."), new CommandLineHelpCommand("remove", "Remove extension from the cache."), }, @@ -76,6 +80,10 @@ public override async Task ExecuteAsync(CancellationToken cancellationToken success = await this.AddExtensions(cacheManager, cancellationToken); break; + case CacheSubcommand.Update: + success = await this.UpdateExtensions(cacheManager, cancellationToken); + break; + case CacheSubcommand.Remove: success = await this.RemoveExtensions(cacheManager, cancellationToken); break; @@ -134,6 +142,19 @@ private async Task AddExtensions(ExtensionCacheManager cacheManager, Cance return success; } + private async Task UpdateExtensions(ExtensionCacheManager cacheManager, CancellationToken cancellationToken) + { + var success = false; + + foreach (var extensionRef in this.ExtensionReferences) + { + var added = await cacheManager.UpdateAsync(this.Global, extensionRef, cancellationToken); + success |= added; + } + + return success; + } + private async Task RemoveExtensions(ExtensionCacheManager cacheManager, CancellationToken cancellationToken) { var success = false;