From ab179997b8eafeb749d7556b0b3c31a97adb63a4 Mon Sep 17 00:00:00 2001
From: Frank Robijn <13610628+frobijn@users.noreply.github.com>
Date: Mon, 16 Dec 2024 16:15:00 +0100
Subject: [PATCH] Firmware archive related bug fixes (#307)
---
nanoFirmwareFlasher.Library/ExitCodes.cs | 8 ++-
.../FirmwareArchiveManager.cs | 34 +++++++++++++
.../FirmwarePackage.cs | 14 +++++-
.../FirmwarePackageTests.cs | 49 ++++++++++++++-----
.../ToolFirmwareArchiveTests.cs | 34 ++++++-------
nanoFirmwareFlasher.Tool/Program.cs | 12 ++---
6 files changed, 113 insertions(+), 38 deletions(-)
diff --git a/nanoFirmwareFlasher.Library/ExitCodes.cs b/nanoFirmwareFlasher.Library/ExitCodes.cs
index 9d664d65..fdcbab18 100644
--- a/nanoFirmwareFlasher.Library/ExitCodes.cs
+++ b/nanoFirmwareFlasher.Library/ExitCodes.cs
@@ -339,7 +339,13 @@ public enum ExitCodes
///
/// Error clearing cache location.
///
- [Display(Name = "Error occured when clearing the firmware cache location.")]
+ [Display(Name = "Error occurred when clearing the firmware cache location.")]
E9014 = 9014,
+
+ ///
+ /// Can't find the target in the firmware archive.
+ ///
+ [Display(Name = "Can't find the target in the firmware archive.")]
+ E9015 = 9015,
}
}
diff --git a/nanoFirmwareFlasher.Library/FirmwareArchiveManager.cs b/nanoFirmwareFlasher.Library/FirmwareArchiveManager.cs
index bd9890de..603c1d91 100644
--- a/nanoFirmwareFlasher.Library/FirmwareArchiveManager.cs
+++ b/nanoFirmwareFlasher.Library/FirmwareArchiveManager.cs
@@ -67,6 +67,40 @@ public List GetTargetList(
return targetPackages;
}
+ ///
+ /// Get the latest version present in the firmware archive for the specified target.
+ ///
+ /// Option for preview version.
+ /// Target to find the latest version of.
+ /// The with details on latest firmware package for the target, or if none is present.
+ public CloudSmithPackageDetail GetLatestVersion(
+ bool preview,
+ string target)
+ {
+ CloudSmithPackageDetail result = null;
+ Version latest = null;
+ if (Directory.Exists(_archivePath) && !string.IsNullOrEmpty(target))
+ {
+ foreach (string filePath in Directory.EnumerateFiles(_archivePath, $"{target}-*{INFOFILE_EXTENSION}"))
+ {
+ PersistedPackageInformation packageInformation = JsonConvert.DeserializeObject(File.ReadAllText(filePath));
+ if (packageInformation is not null && packageInformation.IsPreview == preview)
+ {
+ if (Version.TryParse(packageInformation.Version, out Version version))
+ {
+ if (latest is null || latest < version)
+ {
+ latest = version;
+ result = packageInformation;
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
///
/// Download a firmware package from the repository and add it to the archive directory
///
diff --git a/nanoFirmwareFlasher.Library/FirmwarePackage.cs b/nanoFirmwareFlasher.Library/FirmwarePackage.cs
index e7d9c1dc..41e54ab8 100644
--- a/nanoFirmwareFlasher.Library/FirmwarePackage.cs
+++ b/nanoFirmwareFlasher.Library/FirmwarePackage.cs
@@ -344,6 +344,18 @@ void UpdateLocationPathAndFileName(bool initial)
}
+ if (archiveDirectoryPath is not null && Version is null)
+ {
+ // Find the latest version in the archive directory
+ var archiveManager = new FirmwareArchiveManager(archiveDirectoryPath);
+ Version = archiveManager.GetLatestVersion(_preview, _targetName)?.Version;
+ if (Version is null)
+ {
+ // Package is considered to be not present, even if it does exist in the cache location
+ return (ExitCodes.E9015, null);
+ }
+ }
+
// create the download folder
try
{
@@ -369,7 +381,7 @@ void UpdateLocationPathAndFileName(bool initial)
if (!File.Exists(archiveFileName))
{
// Package is considered to be not present, even if it does exist in the cache location
- return (ExitCodes.E9007, null);
+ return (ExitCodes.E9015, null);
}
if (!skipDownload)
diff --git a/nanoFirmwareFlasher.Tests/FirmwarePackageTests.cs b/nanoFirmwareFlasher.Tests/FirmwarePackageTests.cs
index 026ee919..bfc2b416 100644
--- a/nanoFirmwareFlasher.Tests/FirmwarePackageTests.cs
+++ b/nanoFirmwareFlasher.Tests/FirmwarePackageTests.cs
@@ -194,7 +194,7 @@ where d.StartsWith(targetName + "-")
[TestMethod]
[TestCategory("CloudSmith")]
- public void FirmwarePackage_DebugFirmware_Download()
+ public void FirmwarePackage_LegacyVirtualDevice_Download()
{
#region Setup
using var output = new OutputWriterHelper();
@@ -236,32 +236,55 @@ public void FirmwarePackage_FromArchive()
{
Assert.Inconclusive("Cannot download the ESP32 package.");
}
- string testTargetName = "NO_REAL_TARGET";
- string testVersion = "0.0.0.0";
- File.Copy(Path.Combine(cacheDirectory, package.Name, $"{package.Name}-{package.Version}.zip"), Path.Combine(archiveDirectory, $"{testTargetName}-{testVersion}.zip"));
+ string testTarget1Name = "TARGET1_IN_ARCHIVE_ONLY";
+ string testTarget2Name = "TARGET2_IN_ARCHIVE_ONLY";
+ string testVersion = "1.23.4.5";
+ string testOldVersion = "1.6.7.8";
+
+ // Copy the package to the archive directory, modified for TARGET1_IN_ARCHIVE_ONLY and TARGET2_IN_ARCHIVE_ONLY
+ File.Copy(Path.Combine(cacheDirectory, package.Name, $"{package.Name}-{package.Version}.zip"), Path.Combine(archiveDirectory, $"{testTarget1Name}-{testVersion}.zip"));
+ File.WriteAllText(Path.Combine(archiveDirectory, $"{testTarget1Name}-{testVersion}.zip.json"), $@"{{ ""Name"": ""{testTarget1Name}"", ""Version"": ""{testVersion}"", ""Platform"": ""esp32"" }}");
+ File.Copy(Path.Combine(cacheDirectory, package.Name, $"{package.Name}-{package.Version}.zip"), Path.Combine(archiveDirectory, $"{testTarget2Name}-{testVersion}.zip"));
+ File.WriteAllText(Path.Combine(archiveDirectory, $"{testTarget2Name}-{testVersion}.zip.json"), $@"{{ ""Name"": ""{testTarget2Name}"", ""Version"": ""{testVersion}"", ""Platform"": ""esp32"" }}");
+
+ // Create an invalid package for an earlier version of TARGET2_IN_ARCHIVE_ONLY - this should not be used
+ File.WriteAllText(Path.Combine(archiveDirectory, $"{testTarget2Name}-{testOldVersion}.zip"), "");
+ File.WriteAllText(Path.Combine(archiveDirectory, $"{testTarget2Name}-{testOldVersion}.zip.json"), $@"{{ ""Name"": ""{testTarget2Name}"", ""Version"": ""{testOldVersion}"", ""Platform"": ""esp32"" }}");
#endregion
- #region Get package that exist in the archive directory but not in the repository
+ #region Get package that exist in the archive directory but not in the repository; include version
output.Reset();
- var actual = new Esp32Firmware(testTargetName, testVersion, false, null);
+ var actual = new Esp32Firmware(testTarget1Name, testVersion, false, null);
exitCode = actual.DownloadAndExtractAsync(archiveDirectory).GetAwaiter().GetResult();
Assert.AreEqual(ExitCodes.OK, exitCode);
output.AssertAreEqual("");
- Assert.IsTrue(Directory.Exists(Path.Combine(cacheDirectory, testTargetName)));
- Assert.IsTrue(File.Exists(Path.Combine(cacheDirectory, testTargetName, $"{testTargetName}-{testVersion}.zip")));
- Assert.IsTrue(File.Exists(Path.Combine(cacheDirectory, testTargetName, "nanoCLR.bin")));
+ Assert.IsTrue(Directory.Exists(Path.Combine(cacheDirectory, testTarget1Name)));
+ Assert.IsTrue(File.Exists(Path.Combine(cacheDirectory, testTarget1Name, $"{testTarget1Name}-{testVersion}.zip")));
+ Assert.IsTrue(File.Exists(Path.Combine(cacheDirectory, testTarget1Name, "nanoCLR.bin")));
+ #endregion
+
+ #region Get package that exist in the archive directory but not in the repository; do not include version
+ output.Reset();
+ actual = new Esp32Firmware(testTarget2Name, null, false, null);
+ exitCode = actual.DownloadAndExtractAsync(archiveDirectory).GetAwaiter().GetResult();
+
+ Assert.AreEqual(ExitCodes.OK, exitCode);
+ output.AssertAreEqual("");
+ Assert.IsTrue(Directory.Exists(Path.Combine(cacheDirectory, testTarget2Name)));
+ Assert.IsTrue(File.Exists(Path.Combine(cacheDirectory, testTarget2Name, $"{testTarget2Name}-{testVersion}.zip")));
+ Assert.IsTrue(File.Exists(Path.Combine(cacheDirectory, testTarget2Name, "nanoCLR.bin")));
#endregion
#region Get package that does not exist in the archive directory
- testTargetName = "MISSING_TARGET";
+ testTarget1Name = "MISSING_TARGET";
- actual = new Esp32Firmware(testTargetName, testVersion, false, null);
+ actual = new Esp32Firmware(testTarget1Name, testVersion, false, null);
exitCode = actual.DownloadAndExtractAsync(archiveDirectory).GetAwaiter().GetResult();
- Assert.AreEqual(ExitCodes.E9007, exitCode);
+ Assert.AreEqual(ExitCodes.E9015, exitCode);
output.AssertAreEqual("");
- Assert.IsFalse(File.Exists(Path.Combine(cacheDirectory, testTargetName, $"{testTargetName}-{testVersion}.zip")));
+ Assert.IsFalse(File.Exists(Path.Combine(cacheDirectory, testTarget1Name, $"{testTarget1Name}-{testVersion}.zip")));
#endregion
}
}
diff --git a/nanoFirmwareFlasher.Tests/ToolFirmwareArchiveTests.cs b/nanoFirmwareFlasher.Tests/ToolFirmwareArchiveTests.cs
index 3ac52d92..b7a3a1d2 100644
--- a/nanoFirmwareFlasher.Tests/ToolFirmwareArchiveTests.cs
+++ b/nanoFirmwareFlasher.Tests/ToolFirmwareArchiveTests.cs
@@ -33,21 +33,21 @@ public void FirmwareArchive_Platform_UpdateArchive_ListTargets()
#endregion
#region List empty archive
- int actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromfwarchive", "--fwarchivepath", archiveDirectory])
+ int actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromarchive", "--archivepath", archiveDirectory])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.OK, actual);
#endregion
#region Update archive
output.Reset();
- actual = Program.Main(["--updatefwarchive", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fwarchivepath", archiveDirectory])
+ actual = Program.Main(["--updatearchive", "--platform", $"{SupportedPlatform.ti_simplelink}", "--archivepath", archiveDirectory])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.OK, actual);
#endregion
#region List filled archive
output.Reset();
- actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromfwarchive", "--fwarchivepath", archiveDirectory])
+ actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromarchive", "--archivepath", archiveDirectory])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.OK, actual);
@@ -70,14 +70,14 @@ public void FirmwareArchive_Target_UpdateArchive_ListTargets()
#region Update archive
output.Reset();
- int actual = Program.Main(["--updatefwarchive", "--target", $"{allPackages[0].Name}", "--fwarchivepath", archiveDirectory])
+ int actual = Program.Main(["--updatearchive", "--target", $"{allPackages[0].Name}", "--archivepath", archiveDirectory])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.OK, actual);
#endregion
#region List filled archive
output.Reset();
- actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromfwarchive", "--fwarchivepath", archiveDirectory])
+ actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromarchive", "--archivepath", archiveDirectory])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.OK, actual);
@@ -96,11 +96,11 @@ public void FirmwareArchive_ListTargets_InvalidArguments()
string testDirectory = TestDirectoryHelper.GetTestDirectory(TestContext);
string archiveDirectory = Path.Combine(testDirectory, "archive");
- int actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromfwarchive", "--verbosity", "diagnostic"])
+ int actual = Program.Main(["--listtargets", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromarchive", "--verbosity", "diagnostic"])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.E9000, actual);
- Assert.IsTrue(output.Output.Contains("--fwarchivepath is required when --fromfwarchive is specified."));
+ Assert.IsTrue(output.Output.Contains("--archivepath is required when --fromarchive is specified."));
}
[TestMethod]
@@ -110,25 +110,25 @@ public void FirmwareArchive_UpdateArchive_InvalidArguments()
string testDirectory = TestDirectoryHelper.GetTestDirectory(TestContext);
string archiveDirectory = Path.Combine(testDirectory, "archive");
- int actual = Program.Main(["--updatefwarchive", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromfwarchive", "--verbosity", "diagnostic"])
+ int actual = Program.Main(["--updatearchive", "--platform", $"{SupportedPlatform.ti_simplelink}", "--fromarchive", "--verbosity", "diagnostic"])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.E9000, actual);
- Assert.IsTrue(output.Output.Contains("Incompatible option --fromfwarchive combined with --updatefwarchive."));
+ Assert.IsTrue(output.Output.Contains("Incompatible option --fromarchive combined with --updatearchive."));
output.Reset();
- actual = Program.Main(["--updatefwarchive", "--platform", $"{SupportedPlatform.ti_simplelink}", "--verbosity", "diagnostic"])
+ actual = Program.Main(["--updatearchive", "--platform", $"{SupportedPlatform.ti_simplelink}", "--verbosity", "diagnostic"])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.E9000, actual);
- Assert.IsTrue(output.Output.Contains("--fwarchivepath is required when --updatefwarchive is specified."));
+ Assert.IsTrue(output.Output.Contains("--archivepath is required when --updatearchive is specified."));
output.Reset();
- actual = Program.Main(["--updatefwarchive", "--fwarchivepath", $"{SupportedPlatform.ti_simplelink}", "--verbosity", "diagnostic"])
+ actual = Program.Main(["--updatearchive", "--archivepath", $"{SupportedPlatform.ti_simplelink}", "--verbosity", "diagnostic"])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.E9000, actual);
- Assert.IsTrue(output.Output.Contains("--platform or --target is required when --updatefwarchive is specified."));
+ Assert.IsTrue(output.Output.Contains("--platform or --target is required when --updatearchive is specified."));
}
[TestMethod]
@@ -138,18 +138,18 @@ public void FirmwareArchive_UpdateFirmware_InvalidArguments()
string testDirectory = TestDirectoryHelper.GetTestDirectory(TestContext);
string archiveDirectory = Path.Combine(testDirectory, "archive");
- int actual = Program.Main(["--serialport", "COM3", "--target", "SOME_TARGET", "--fromfwarchive", "--verbosity", "diagnostic"])
+ int actual = Program.Main(["--serialport", "COM3", "--target", "SOME_TARGET", "--fromarchive", "--verbosity", "diagnostic"])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.E9000, actual);
- Assert.IsTrue(output.Output.Contains("--fwarchivepath is required when --fromfwarchive is specified."));
+ Assert.IsTrue(output.Output.Contains("--archivepath is required when --fromarchive is specified."));
output.Reset();
- actual = Program.Main(["--serialport", "COM3", "--target", "SOME_TARGET", "--fwarchivepath", archiveDirectory, "--verbosity", "diagnostic"])
+ actual = Program.Main(["--serialport", "COM3", "--target", "SOME_TARGET", "--archivepath", archiveDirectory, "--verbosity", "diagnostic"])
.GetAwaiter().GetResult();
Assert.AreEqual((int)ExitCodes.E9000, actual);
- Assert.IsTrue(output.Output.Contains("--fromfwarchive is required when --fwarchivepath is specified."));
+ Assert.IsTrue(output.Output.Contains("--fromarchive is required when --archivepath is specified."));
}
}
}
diff --git a/nanoFirmwareFlasher.Tool/Program.cs b/nanoFirmwareFlasher.Tool/Program.cs
index 28e69dc6..e45b0f2c 100644
--- a/nanoFirmwareFlasher.Tool/Program.cs
+++ b/nanoFirmwareFlasher.Tool/Program.cs
@@ -289,7 +289,7 @@ static async Task RunOptionsAndReturnExitCodeAsync(Options o)
if (string.IsNullOrEmpty(o.FwArchivePath))
{
_exitCode = ExitCodes.E9000;
- _extraMessage = "--fwarchivepath is required when --fromfwarchive is specified.";
+ _extraMessage = "--archivepath is required when --fromarchive is specified.";
return;
}
@@ -558,20 +558,20 @@ static async Task RunOptionsAndReturnExitCodeAsync(Options o)
if (o.FromFwArchive)
{
_exitCode = ExitCodes.E9000;
- _extraMessage = "Incompatible option --fromfwarchive combined with --updatefwarchive.";
+ _extraMessage = "Incompatible option --fromarchive combined with --updatearchive.";
return;
}
if (string.IsNullOrEmpty(o.FwArchivePath))
{
_exitCode = ExitCodes.E9000;
- _extraMessage = $"--fwarchivepath is required when --updatefwarchive is specified.";
+ _extraMessage = $"--archivepath is required when --updatearchive is specified.";
return;
}
if (o.Platform is null && string.IsNullOrEmpty(o.TargetName))
{
_exitCode = ExitCodes.E9000;
- _extraMessage = $"--platform or --target is required when --updatefwarchive is specified.";
+ _extraMessage = $"--platform or --target is required when --updatearchive is specified.";
return;
}
@@ -591,14 +591,14 @@ static async Task RunOptionsAndReturnExitCodeAsync(Options o)
if (o.FromFwArchive)
{
_exitCode = ExitCodes.E9000;
- _extraMessage = $"--fwarchivepath is required when --fromfwarchive is specified.";
+ _extraMessage = $"--archivepath is required when --fromarchive is specified.";
return;
}
}
else if (!o.FromFwArchive)
{
_exitCode = ExitCodes.E9000;
- _extraMessage = $"--fromfwarchive is required when --fwarchivepath is specified.";
+ _extraMessage = $"--fromarchive is required when --archivepath is specified.";
return;
}
#endregion