diff --git a/src/NetSparkle.Tests.AppCastGenerator/AppCastMakerTests.cs b/src/NetSparkle.Tests.AppCastGenerator/AppCastMakerTests.cs index c0fd9d73..25a38f09 100644 --- a/src/NetSparkle.Tests.AppCastGenerator/AppCastMakerTests.cs +++ b/src/NetSparkle.Tests.AppCastGenerator/AppCastMakerTests.cs @@ -70,6 +70,7 @@ public void CanGetVersionFromName() Assert.Null(AppCastMaker.GetVersionFromName(null)); Assert.Null(AppCastMaker.GetVersionFromName("foo")); Assert.Null(AppCastMaker.GetVersionFromName("foo1.")); + Assert.Null(AppCastMaker.GetVersionFromName("hello 1.txt")); // New test, 1 is not a valid version, should be atleast Major.Minor Assert.Equal("1.0", AppCastMaker.GetVersionFromName("hello 1.0.txt")); Assert.Equal("1.0", AppCastMaker.GetVersionFromName("hello 1.0 .txt")); // whitespace shouldn't matter Assert.Null(AppCastMaker.GetVersionFromName("hello 1 .0.txt")); // I changed this to null as I think its a more suitable output versus a version of 0 @@ -77,6 +78,8 @@ public void CanGetVersionFromName() Assert.Equal("4.3.2", AppCastMaker.GetVersionFromName("My Favorite App 4.3.2.zip")); Assert.Equal("1.0", AppCastMaker.GetVersionFromName("foo1.0")); Assert.Equal("0.1", AppCastMaker.GetVersionFromName("foo0.1")); + Assert.Equal("0.1", AppCastMaker.GetVersionFromName("foo 0.1")); + Assert.Equal("0.1", AppCastMaker.GetVersionFromName("foo_0.1")); Assert.Equal("0.1", AppCastMaker.GetVersionFromName("0.1foo")); Assert.Equal("0.1", AppCastMaker.GetVersionFromName("0.1 My App")); Assert.Equal("0.0.3.1", AppCastMaker.GetVersionFromName("foo0.0.3.1")); @@ -550,7 +553,7 @@ public void SingleDigitVersionDoesNotFail() // setup test dir var tempDir = GetCleanTempDir(); // create dummy files - var dummyFilePath = Path.Combine(tempDir, "hello 1.txt"); + var dummyFilePath = Path.Combine(tempDir, "hello 1.0.txt"); const int fileSizeBytes = 57; var tempData = RandomString(fileSizeBytes); File.WriteAllText(dummyFilePath, tempData); @@ -582,8 +585,8 @@ public void SingleDigitVersionDoesNotFail() } Assert.Single(items); - Assert.Equal("1", items[0].Version); - Assert.Equal("https://example.com/downloads/hello%201.txt", items[0].DownloadLink); + Assert.Equal("1.0", items[0].Version); + Assert.Equal("https://example.com/downloads/hello%201.0.txt", items[0].DownloadLink); Assert.True(items[0].DownloadSignature.Length > 0); Assert.True(items[0].IsWindowsUpdate); Assert.Equal(fileSizeBytes, items[0].UpdateSize); diff --git a/src/NetSparkle.Tools.AppCastGenerator/AppCastMaker.cs b/src/NetSparkle.Tools.AppCastGenerator/AppCastMaker.cs index 5f9309dd..61522b0d 100644 --- a/src/NetSparkle.Tools.AppCastGenerator/AppCastMaker.cs +++ b/src/NetSparkle.Tools.AppCastGenerator/AppCastMaker.cs @@ -85,6 +85,9 @@ public static string GetVersionFromName(string fullFileNameWithPath, string bina // Replace multiple spaces with a single space fullFileNameWithPath = Regex.Replace(fullFileNameWithPath, @"\s+", " "); + // Replace _ with space + fullFileNameWithPath = fullFileNameWithPath.Replace("_", " "); + // Regex for simple version numbers (X.X.X or X.X.X.X) string simpleVersionPattern = @"^\d+(\.\d+){1,3}$"; @@ -139,160 +142,165 @@ string RemoveTextBlockFromRight(string input) return input; } - // Split the filename by space to find the version segment - var parts = fullFileNameWithPath.Split(' '); + var folderSplit = fullFileNameWithPath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries); - // If there are multiple parts, we check the first and last parts only assuming version is in either - // If the strings in the start and end both produce valid versions, we return the version from the end - // If single string no spaces, we take the entire string and check it from left and right - string leftPart = null; - string rightPart = null; - if (parts.Length > 1) - { - leftPart = parts[0]; - rightPart = parts[^1]; - } - else + // Loop through the last 4 folder names to find the version + for (int j = folderSplit.Length - 1; j >= Math.Max(0, folderSplit.Length - 4); j--) { - leftPart = parts[0]; - rightPart = parts[0]; - } + var fileName = folderSplit[j]; - // Checking left part with logic from left - string lastValidVersionLeft = null; - if (!string.IsNullOrEmpty(leftPart)) - { - // Remove any text block from left - // For example 0.1foo becomes 0.1, 0.1-foo stays 0.1-foo, 0.1+foo stays 0.1+foo - leftPart = RemoveTextBlockFromLeft(leftPart); + // Split the filename by space to find the version segment + var parts = fileName.Split(' '); - // Make sure leftpart has a number - if (Regex.IsMatch(leftPart, @"\d")) + // If there are multiple parts, we check the first and last parts only assuming version is in either + // If the strings in the start and end both produce valid versions, we return the version from the end + // If single string no spaces, we take the entire string and check it from left and right + string leftPart = null; + string rightPart = null; + if (parts.Length > 1) { - // Check if its only numeric values and a simple version for quick check - if (Regex.IsMatch(leftPart, @"^[\d.]+$") && IsValidVersion(leftPart)) - { - lastValidVersionLeft = leftPart; - } - else + leftPart = parts[0]; + rightPart = parts[^1]; + } + else + { + leftPart = parts[0]; + rightPart = parts[0]; + } + + // Checking left part with logic from left + string lastValidVersionLeft = null; + if (!string.IsNullOrEmpty(leftPart)) + { + // Remove any text block from left + // For example 0.1foo becomes 0.1, 0.1-foo stays 0.1-foo, 0.1+foo stays 0.1+foo + leftPart = RemoveTextBlockFromLeft(leftPart); + + // Make sure leftpart has a number + if (Regex.IsMatch(leftPart, @"\d")) { - // Its more complex so we check if its semantic version before splitting - if (IsValidVersion(leftPart)) + // Check if its only numeric values and a simple version for quick check + if (Regex.IsMatch(leftPart, @"^[\d.]+$") && IsValidVersion(leftPart)) { lastValidVersionLeft = leftPart; } else { - // Start splitting and going from left to right - // Keep record of last applicable version and check one more segment after it, if it fails then the last one we found is what we need - var segments = leftPart.Split('.'); - string tempSegment = ""; - bool lastVersionToCheck = false; - for (int i = segments.Length - 1; i >= 0; i--) + // Its more complex so we check if its semantic version before splitting + if (IsValidVersion(leftPart)) + { + lastValidVersionLeft = leftPart; + } + else { - var segment = segments[i]; - if (Regex.IsMatch(segment, @"[a-zA-Z]") && Regex.IsMatch(segment, @"\d")) + // Start splitting and going from left to right + // Keep record of last applicable version and check one more segment after it, if it fails then the last one we found is what we need + var segments = leftPart.Split('.'); + string tempSegment = ""; + bool lastVersionToCheck = false; + for (int i = segments.Length - 1; i >= 0; i--) { - var match = Regex.Match(segment, @"[^+-]*[a-zA-Z]"); - if (match.Success) + var segment = segments[i]; + if (Regex.IsMatch(segment, @"[a-zA-Z]") && Regex.IsMatch(segment, @"\d")) { - segment = segment.Substring(match.Index + match.Length); - lastVersionToCheck = true; + var match = Regex.Match(segment, @"[^+-]*[a-zA-Z]"); + if (match.Success) + { + segment = segment.Substring(match.Index + match.Length); + lastVersionToCheck = true; + } } - } - tempSegment = string.IsNullOrEmpty(tempSegment) ? segment : segment + "." + tempSegment; - tempSegment = tempSegment.Trim('.'); + tempSegment = string.IsNullOrEmpty(tempSegment) ? segment : segment + "." + tempSegment; + tempSegment = tempSegment.Trim('.'); - if (IsValidVersion(tempSegment)) - { - lastValidVersionLeft = tempSegment; - } + if (IsValidVersion(tempSegment)) + { + lastValidVersionLeft = tempSegment; + } - if (lastVersionToCheck) - { - break; + if (lastVersionToCheck) + { + break; + } } } } } } - } - // Checking right part with logic from right - string lastValidVersionRight = null; - if (!string.IsNullOrEmpty(rightPart)) - { - // Remove any text block from right - // For example foo0.1 becomes 0.1 - rightPart = RemoveTextBlockFromRight(rightPart); - - // Make sure rightpart has a number - if (Regex.IsMatch(rightPart, @"\d")) + // Checking right part with logic from right + string lastValidVersionRight = null; + if (!string.IsNullOrEmpty(rightPart)) { - // Check if its only numeric values and a simple version for quick check - if (Regex.IsMatch(rightPart, @"^[\d.]+$") && IsValidVersion(rightPart)) - { - lastValidVersionRight = rightPart; - } - else + // Remove any text block from right + // For example foo0.1 becomes 0.1 + rightPart = RemoveTextBlockFromRight(rightPart); + + // Make sure rightpart has a number + if (Regex.IsMatch(rightPart, @"\d")) { - // Its more complex so we check if its semantic version before splitting - if (IsValidVersion(rightPart)) + // Check if its only numeric values and a simple version for quick check + if (Regex.IsMatch(rightPart, @"^[\d.]+$") && IsValidVersion(rightPart)) { lastValidVersionRight = rightPart; } else { - // Start splitting and going from left to right - // Keep record of last applicable version and check one more segment after it, if it fails then the last one we found is what we need - var segments = rightPart.Split('.'); - string tempSegment = ""; - bool lastVersionToCheck = false; - for (int i = segments.Length - 1; i >= 0; i--) + // Its more complex so we check if its semantic version before splitting + if (IsValidVersion(rightPart)) + { + lastValidVersionRight = rightPart; + } + else { - var segment = segments[i]; - if (Regex.IsMatch(segment, @"[a-zA-Z]") && Regex.IsMatch(segment, @"\d")) + // Start splitting and going from left to right + // Keep record of last applicable version and check one more segment after it, if it fails then the last one we found is what we need + var segments = rightPart.Split('.'); + string tempSegment = ""; + bool lastVersionToCheck = false; + for (int i = segments.Length - 1; i >= 0; i--) { - var match = Regex.Match(segment, @"[^+-]*[a-zA-Z]"); - if (match.Success) + var segment = segments[i]; + if (Regex.IsMatch(segment, @"[a-zA-Z]") && Regex.IsMatch(segment, @"\d")) { - segment = segment.Substring(match.Index + match.Length); - lastVersionToCheck = true; + var match = Regex.Match(segment, @"[^+-]*[a-zA-Z]"); + if (match.Success) + { + segment = segment.Substring(match.Index + match.Length); + lastVersionToCheck = true; + } } - } - tempSegment = string.IsNullOrEmpty(tempSegment) ? segment : segment + "." + tempSegment; - tempSegment = tempSegment.Trim('.'); + tempSegment = string.IsNullOrEmpty(tempSegment) ? segment : segment + "." + tempSegment; + tempSegment = tempSegment.Trim('.'); - if (IsValidVersion(tempSegment)) - { - lastValidVersionRight = tempSegment; - } + if (IsValidVersion(tempSegment)) + { + lastValidVersionRight = tempSegment; + } - if (lastVersionToCheck) - { - break; + if (lastVersionToCheck) + { + break; + } } } } } } - } - // Right part is preferred over left part - if (lastValidVersionRight != null) - { - return lastValidVersionRight; - } - else if (lastValidVersionLeft != null) - { - return lastValidVersionLeft; - } - else - { - return null; + // Right part is preferred over left part + if (lastValidVersionRight != null) + { + return lastValidVersionRight; + } + else if (lastValidVersionLeft != null) + { + return lastValidVersionLeft; + } } + return null; } public static string GetVersionFromAssembly(string fullFileNameWithPath)