Skip to content

Commit

Permalink
Improve ZIP handling in interactive update (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdanish-kh authored Jul 10, 2023
1 parent 6c7981a commit 6dfdb12
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 27 deletions.
29 changes: 29 additions & 0 deletions src/WingetCreateCLI/Commands/BaseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,35 @@ protected static void RemoveEmptyStringFieldsInManifests(Manifests manifests)
{
RemoveEmptyStringFields(installer);
}
}

/// <summary>
/// Shifts common installer fields from root to installer level.
/// </summary>
/// <param name="installerManifest">Wrapper object containing the installer manifest object models.</param>
protected static void ShiftFieldsFromRootToInstallerLevel(InstallerManifest installerManifest)
{
var rootProperties = installerManifest.GetType().GetProperties();
var installerProperties = installerManifest.Installers.First().GetType().GetProperties();

// Get common properties between root and installer level
var commonProperties = rootProperties.Where(p => installerProperties.Any(ip => ip.Name == p.Name));

foreach (var property in commonProperties)
{
var rootValue = property.GetValue(installerManifest);
if (rootValue != null)
{
foreach (var installer in installerManifest.Installers)
{
// Copy the value to installer level
installer.GetType().GetProperty(property.Name).SetValue(installer, rootValue);
}

// Set root value to null
property.SetValue(installerManifest, null);
}
}
}

/// <summary>
Expand Down
78 changes: 51 additions & 27 deletions src/WingetCreateCLI/Commands/UpdateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,32 +280,7 @@ public async Task<Manifests> UpdateManifestsAutonomously(Manifests manifests)

// Obtain all possible relative file paths and check if there is a match.
List<string> relativeFilePaths = installerManifest.Installers.SelectMany(i => i.NestedInstallerFiles.Select(x => x.RelativeFilePath)).Distinct().ToList();
string extractDirectory = Path.Combine(PackageParser.InstallerDownloadPath, Path.GetFileNameWithoutExtension(packageFile));

if (Directory.Exists(extractDirectory))
{
Directory.Delete(extractDirectory, true);
}

try
{
ZipFile.ExtractToDirectory(packageFile, extractDirectory, true);
}
catch (Exception ex)
{
if (ex is InvalidDataException || ex is IOException || ex is NotSupportedException)
{
Logger.ErrorLocalized(nameof(Resources.InvalidZipFile_ErrorMessage), ex);
return null;
}
else if (ex is PathTooLongException)
{
Logger.ErrorLocalized(nameof(Resources.ZipPathExceedsMaxLength_ErrorMessage), ex);
return null;
}

throw;
}
string extractDirectory = ExtractArchiveAndRetrieveDirectoryPath(packageFile);

installerUpdate.RelativeFilePaths = new List<string>();

Expand Down Expand Up @@ -410,6 +385,37 @@ public Manifests DeserializeManifestContentAndApplyInitialUpdate(List<string> la
return manifests;
}

private static string ExtractArchiveAndRetrieveDirectoryPath(string packageFilePath)
{
string extractDirectory = Path.Combine(PackageParser.InstallerDownloadPath, Path.GetFileNameWithoutExtension(packageFilePath));

if (Directory.Exists(extractDirectory))
{
Directory.Delete(extractDirectory, true);
}

try
{
ZipFile.ExtractToDirectory(packageFilePath, extractDirectory, true);
return extractDirectory;
}
catch (Exception ex)
{
if (ex is InvalidDataException || ex is IOException || ex is NotSupportedException)
{
Logger.ErrorLocalized(nameof(Resources.InvalidZipFile_ErrorMessage), ex);
return null;
}
else if (ex is PathTooLongException)
{
Logger.ErrorLocalized(nameof(Resources.ZipPathExceedsMaxLength_ErrorMessage), ex);
return null;
}

throw;
}
}

private static Manifests ConvertSingletonToMultifileManifest(WingetCreateCore.Models.Singleton.SingletonManifest singletonManifest)
{
// Create automapping configuration
Expand Down Expand Up @@ -660,6 +666,7 @@ private async Task<Manifests> UpdateManifestsInteractively(Manifests manifests)

// Clone the list of installers in order to preserve initial values.
Manifests originalManifest = new Manifests { InstallerManifest = new InstallerManifest() };
ShiftFieldsFromRootToInstallerLevel(manifests.InstallerManifest);
originalManifest.InstallerManifest.Installers = manifests.CloneInstallers();

do
Expand Down Expand Up @@ -722,7 +729,24 @@ private async Task UpdateSingleInstallerInteractively(Installer installer)
{
continue;
}
else if (!PackageParser.ParsePackageAndUpdateInstallerNode(installer, packageFile, url))

if (packageFile.IsZipFile())
{
string extractDirectory = ExtractArchiveAndRetrieveDirectoryPath(packageFile);
string relativeFilePath = installer.NestedInstallerFiles.First().RelativeFilePath;
string pathToNestedInstaller = Path.Combine(extractDirectory, relativeFilePath);
if (File.Exists(pathToNestedInstaller))
{
packageFile = pathToNestedInstaller;
}
else
{
Logger.ErrorLocalized(nameof(Resources.UnmatchedNestedInstaller_Error), relativeFilePath, url);
continue;
}
}

if (!PackageParser.ParsePackageAndUpdateInstallerNode(installer, packageFile, url))
{
Logger.ErrorLocalized(nameof(Resources.PackageParsing_Error), url);
Console.WriteLine();
Expand Down
9 changes: 9 additions & 0 deletions src/WingetCreateCLI/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/WingetCreateCLI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,9 @@
<data name="Example_UpdateCommand_OverrideScope" xml:space="preserve">
<value>Override the scope of an installer</value>
</data>
<data name="UnmatchedNestedInstaller_Error" xml:space="preserve">
<value>No matches found for "{0}" from {1}</value>
</data>
<data name="IconFileType_KeywordDescription" xml:space="preserve">
<value>The icon file type</value>
</data>
Expand Down

0 comments on commit 6dfdb12

Please sign in to comment.