Fix incorrect hash for ZIP installers in interactive update (#528)

This commit is contained in:
Muhammad Danish 2024-04-03 11:49:01 +05:00 коммит произвёл GitHub
Родитель 9be3d9fbb9
Коммит c8044491be
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 55 добавлений и 9 удалений

Просмотреть файл

@ -864,6 +864,7 @@ namespace Microsoft.WingetCreateCLI.Commands
string url = Prompt.Input<string>(Resources.NewInstallerUrl_Message, null, null, new[] { FieldValidation.ValidateProperty(newInstaller, nameof(Installer.InstallerUrl)) });
string packageFile = await DownloadPackageFile(url);
string archivePath = null;
if (string.IsNullOrEmpty(packageFile))
{
@ -872,6 +873,7 @@ namespace Microsoft.WingetCreateCLI.Commands
if (packageFile.IsZipFile())
{
archivePath = packageFile;
string extractDirectory = ExtractArchiveAndRetrieveDirectoryPath(packageFile);
bool isRelativePathNull = false;
@ -894,7 +896,7 @@ namespace Microsoft.WingetCreateCLI.Commands
packageFile = Path.Combine(extractDirectory, installer.NestedInstallerFiles.First().RelativeFilePath);
}
if (!PackageParser.ParsePackageAndUpdateInstallerNode(installer, packageFile, url))
if (!PackageParser.ParsePackageAndUpdateInstallerNode(installer, packageFile, url, archivePath))
{
Logger.ErrorLocalized(nameof(Resources.PackageParsing_Error), url);
Console.WriteLine();

Просмотреть файл

@ -277,15 +277,22 @@ namespace Microsoft.WingetCreateCore
/// Parses the package for relevant metadata and and updates the metadata of the provided installer node.
/// </summary>
/// <param name="installer">Installer node.</param>
/// <param name="path">Path to package file.</param>
/// <param name="filePath">Path to package file.</param>
/// <param name="url">Installer url.</param>
/// <param name="archivePath">Path to archive file containing the installer. Required if the installer type is Zip.</param>
/// <returns>Boolean indicating whether the package parse was successful.</returns>
public static bool ParsePackageAndUpdateInstallerNode(Installer installer, string path, string url)
public static bool ParsePackageAndUpdateInstallerNode(Installer installer, string filePath, string url, string archivePath = null)
{
// Guard clause to ensure that the archivePath is provided if the installer type is Zip.
if (installer.InstallerType == InstallerType.Zip && string.IsNullOrEmpty(archivePath))
{
return false;
}
List<Installer> newInstallers = new List<Installer>();
bool parseResult = ParseExeInstallerType(path, installer, newInstallers) ||
ParseMsix(path, installer, null, newInstallers) ||
ParseMsi(path, installer, null, newInstallers);
bool parseResult = ParseExeInstallerType(filePath, installer, newInstallers) ||
ParseMsix(filePath, installer, null, newInstallers) ||
ParseMsi(filePath, installer, null, newInstallers);
if (!parseResult || !newInstallers.Any())
{
@ -302,11 +309,11 @@ namespace Microsoft.WingetCreateCore
else
{
// For a single installer, detect the architecture. If no architecture is detected, default to architecture from existing manifest.
newInstaller.Architecture = GetArchFromUrl(url) ?? GetMachineType(path)?.ToString().ToEnumOrDefault<Architecture>() ?? installer.Architecture;
newInstaller.Architecture = GetArchFromUrl(url) ?? GetMachineType(filePath)?.ToString().ToEnumOrDefault<Architecture>() ?? installer.Architecture;
}
newInstaller.InstallerUrl = url;
newInstaller.InstallerSha256 = GetFileHash(path);
newInstaller.InstallerSha256 = string.IsNullOrEmpty(archivePath) ? GetFileHash(filePath) : GetFileHash(archivePath);
UpdateInstallerMetadata(installer, newInstallers.First());
return true;
}

Просмотреть файл

@ -3,8 +3,10 @@
namespace Microsoft.WingetCreateUnitTests
{
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using AutoMapper;
using Microsoft.WingetCreateCore;
@ -157,13 +159,47 @@ namespace Microsoft.WingetCreateUnitTests
WingetCreateCore.Models.Singleton.Installer initialInstaller = initialManifests.SingletonManifest.Installers.First();
Installer installer = ConvertSingletonInstaller(initialInstaller);
PackageParser.ParsePackageAndUpdateInstallerNode(installer, testMsiInstallerPath, installer.InstallerUrl);
bool result = PackageParser.ParsePackageAndUpdateInstallerNode(installer, testMsiInstallerPath, installer.InstallerUrl);
ClassicAssert.IsTrue(result, "ParsePackageAndUpdateInstallerNode should return true.");
ClassicAssert.AreEqual(InstallerType.Msi, installer.InstallerType, "InstallerType should be updated.");
ClassicAssert.AreEqual(initialInstaller.Architecture.ToEnumAttributeValue(), installer.Architecture.ToEnumAttributeValue(), "Architecture should not change.");
ClassicAssert.AreNotEqual(initialInstaller.InstallerSha256, installer.InstallerSha256, "InstallerSha256 should be updated.");
ClassicAssert.AreEqual("{E2650EFC-DCD3-4FAA-BBAC-FD1812B03A61}", installer.ProductCode, "ProductCode should be updated");
}
/// <summary>
/// Validates that the ParsePackageAndUpdateInstallerNode function works as expected for a zip installer.
/// </summary>
[Test]
public void ParseAndUpdateZipInstaller()
{
var testZipInstaller = TestUtils.MockDownloadFile(TestConstants.TestZipInstaller);
Assert.That(testZipInstaller, Is.Not.Null.And.Not.Empty);
string extractDirectory = Path.Combine(PackageParser.InstallerDownloadPath, Path.GetFileNameWithoutExtension(testZipInstaller));
try
{
ZipFile.ExtractToDirectory(testZipInstaller, extractDirectory, true);
}
catch (Exception e)
{
ClassicAssert.Fail($"Failed to extract the zip file: {e.Message}");
}
List<string> initialManifestContent = TestUtils.GetInitialManifestContent($"TestPublisher.ZipWithExe.yaml");
Manifests initialManifests = Serialization.DeserializeManifestContents(initialManifestContent);
WingetCreateCore.Models.Singleton.Installer initialInstaller = initialManifests.SingletonManifest.Installers.First();
Installer installer = ConvertSingletonInstaller(initialInstaller);
string nestedInstallerPath = Path.Combine(extractDirectory, installer.NestedInstallerFiles.First().RelativeFilePath);
bool result = PackageParser.ParsePackageAndUpdateInstallerNode(installer, nestedInstallerPath, installer.InstallerUrl, testZipInstaller);
ClassicAssert.IsTrue(result, "ParsePackageAndUpdateInstallerNode should return true.");
ClassicAssert.AreEqual(InstallerType.Zip, installer.InstallerType, "InstallerType should not change");
ClassicAssert.AreEqual(initialInstaller.Architecture.ToEnumAttributeValue(), installer.Architecture.ToEnumAttributeValue(), "Architecture should not change.");
ClassicAssert.AreNotEqual(initialInstaller.InstallerSha256, installer.InstallerSha256, "InstallerSha256 should be updated");
ClassicAssert.AreEqual(installer.InstallerSha256, PackageParser.GetFileHash(testZipInstaller), "InstallSha256 should match the hash of the zip file");
}
/// <summary>
/// Converts the SingletonManifest Installer object model to the InstallerManifest Installer object model.
/// </summary>
@ -175,6 +211,7 @@ namespace Microsoft.WingetCreateUnitTests
{
cfg.AllowNullCollections = true;
cfg.CreateMap<WingetCreateCore.Models.Singleton.Dependencies, WingetCreateCore.Models.Installer.Dependencies>();
cfg.CreateMap<WingetCreateCore.Models.Singleton.NestedInstallerFile, WingetCreateCore.Models.Installer.NestedInstallerFile>();
cfg.CreateMap<WingetCreateCore.Models.Singleton.Installer, WingetCreateCore.Models.Installer.Installer>();
cfg.CreateMap<WingetCreateCore.Models.Singleton.InstallerSwitches, WingetCreateCore.Models.Installer.InstallerSwitches>();
});