diff --git a/app/Build/Commands/UpdateMetadataCommands.cs b/app/Build/Commands/UpdateMetadataCommands.cs
index e0145f9b1..9630e5155 100644
--- a/app/Build/Commands/UpdateMetadataCommands.cs
+++ b/app/Build/Commands/UpdateMetadataCommands.cs
@@ -259,7 +259,7 @@ public sealed partial class UpdateMetadataCommands
var foundIssue = false;
foreach (var buildOutputLine in dotnetBuildOutputLines)
{
- if(buildOutputLine.Contains(" error ") || buildOutputLine.Contains("#warning"))
+ if(IsDotnetBuildIssue(buildOutputLine))
{
if(!foundIssue)
{
@@ -348,7 +348,7 @@ public sealed partial class UpdateMetadataCommands
var foundRustIssue = false;
foreach (var buildOutputLine in rustBuildOutputLines)
{
- if(buildOutputLine.Contains("error", StringComparison.OrdinalIgnoreCase) || buildOutputLine.Contains("warning"))
+ if(IsRustBuildIssue(buildOutputLine))
{
if(!foundRustIssue)
{
@@ -372,6 +372,42 @@ public sealed partial class UpdateMetadataCommands
}
}
+ ///
+ /// Whether a line of the .NET build output is an error or the warning of a #warning directive.
+ ///
+ ///
+ /// MSBuild writes its diagnostics as "origin: error CODE: text" and keeps the keyword English in any
+ /// language. Looking for the word alone would also catch messages which merely mention an error.
+ ///
+ /// One line of the build output.
+ /// True, when the line reports an issue.
+ private static bool IsDotnetBuildIssue(string line) => DotnetErrorRegex().IsMatch(line) || line.Contains("#warning", StringComparison.Ordinal);
+
+ ///
+ /// Whether a line of the Rust build output is an error or a warning.
+ ///
+ ///
+ /// Cargo and rustc start each diagnostic at the beginning of a line, with "error:", "error[", or "warning:".
+ /// Looking for these words anywhere would also catch the names of crates such as thiserror, which cargo
+ /// prints while compiling them. The note about dependencies which a future Rust version will reject also
+ /// starts with "warning:", yet it says nothing about this build. The Tauri CLI reports its own failures
+ /// with a right-aligned "Error" label.
+ ///
+ /// One line of the build output.
+ /// True, when the line reports an issue.
+ private static bool IsRustBuildIssue(string line)
+ {
+ const string FUTURE_INCOMPATIBILITY_NOTE = "warning: the following packages contain code that will be rejected by a future version of Rust";
+
+ if (line.StartsWith(FUTURE_INCOMPATIBILITY_NOTE, StringComparison.Ordinal))
+ return false;
+
+ return line.StartsWith("error:", StringComparison.Ordinal)
+ || line.StartsWith("error[", StringComparison.Ordinal)
+ || line.StartsWith("warning:", StringComparison.Ordinal)
+ || TauriErrorRegex().IsMatch(line);
+ }
+
private async Task CreateNextChangelog(int currentBuildNumber, AppVersion currentAppVersion)
{
Console.Write("- Create the next changelog ...");
@@ -525,7 +561,6 @@ public sealed partial class UpdateMetadataCommands
return new(
metadataPath,
- metadataContent,
metadataLines,
appVersion,
buildNumber,
@@ -558,8 +593,7 @@ public sealed partial class UpdateMetadataCommands
releaseState.MetadataLines[BUILD_TIME_INDEX] = buildTimeString;
releaseState.MetadataLines[BUILD_NUMBER_INDEX] = buildNumber.ToString(CultureInfo.InvariantCulture);
releaseState.MetadataLines[COMMIT_HASH_INDEX] = $"{releaseState.HeadCommitHash}, release";
- var updatedMetadata = JoinLines(releaseState.MetadataContent, releaseState.MetadataLines);
- await File.WriteAllTextAsync(releaseState.MetadataPath, updatedMetadata, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(releaseState.MetadataPath, releaseState.MetadataLines);
var updatedChangelogHeader = FormatChangelogHeader(releaseState.AppVersion, buildNumber, buildTime);
var updatedChangelog = ReplaceExactlyOnce(releaseState.ChangelogContent, releaseState.ChangelogHeader, updatedChangelogHeader);
@@ -767,10 +801,20 @@ public sealed partial class UpdateMetadataCommands
return content.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n');
}
- private static string JoinLines(string originalContent, string[] lines)
+ ///
+ /// Writes the metadata file with a line feed after each line, the last one included.
+ ///
+ ///
+ /// This is the form in which the file is committed, and the build script of the Rust runtime writes it
+ /// the same way. File.WriteAllLinesAsync would end the lines with the line break of the current OS, so
+ /// that the file would change with the OS it was last built on.
+ ///
+ /// The path of the metadata file.
+ /// The lines to write. An empty element after the final line break, as SplitLines leaves it, adds no empty line.
+ private static async Task WriteMetadataLinesAsync(string pathMetadata, IEnumerable lines)
{
- var lineEnding = originalContent.Contains("\r\n", StringComparison.Ordinal) ? "\r\n" : "\n";
- return string.Join(lineEnding, lines);
+ var metadata = string.Join('\n', lines).TrimEnd('\n') + '\n';
+ await File.WriteAllTextAsync(pathMetadata, metadata, Environment.UTF8_NO_BOM);
}
private async Task ReadPdfiumVersion()
@@ -794,7 +838,7 @@ public sealed partial class UpdateMetadataCommands
Console.Write($"- Updating architecture to {rid.ToUserFriendlyName()} ...");
lines[ARCHITECTURE_INDEX] = rid.AsMicrosoftRid();
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
Console.WriteLine(" done.");
}
@@ -813,7 +857,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updating commit hash from '{currentCommitHash}' to '{updatedCommitHash}'.");
lines[COMMIT_HASH_INDEX] = updatedCommitHash;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
}
private async Task UpdateAppVersion(PrepareAction action, string? version = null)
@@ -876,7 +920,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updating app version from '{currentAppVersionLine}' to '{updatedAppVersion}'.");
lines[APP_VERSION_INDEX] = updatedAppVersion;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
return new(updatedAppVersion, newMajor, newMinor, newPatch);
}
@@ -935,7 +979,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updated Tauri version from {currentTauriVersion} to {updatedTauriVersion}.");
lines[TAURI_VERSION_INDEX] = updatedTauriVersion;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
}
private async Task UpdateVectorStoreVersion()
@@ -960,7 +1004,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updated vector store version from {currentVectorStoreVersion} to {updatedVectorStoreVersion}.");
lines[VECTOR_STORE_VERSION_INDEX] = updatedVectorStoreVersion;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
}
private async Task UpdateMudBlazorVersion()
@@ -985,7 +1029,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updated MudBlazor version from {currentMudBlazorVersion} to {updatedMudBlazorVersion}.");
lines[MUD_BLAZOR_VERSION_INDEX] = updatedMudBlazorVersion;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
}
private async Task UpdateRustVersion()
@@ -1009,7 +1053,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updated Rust version from {currentRustVersion} to {updatedRustVersion}.");
lines[RUST_VERSION_INDEX] = updatedRustVersion;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
}
private async Task UpdateDotnetVersion()
@@ -1040,7 +1084,7 @@ public sealed partial class UpdateMetadataCommands
lines[DOTNET_VERSION_INDEX] = updatedDotnetVersion;
lines[DOTNET_SDK_VERSION_INDEX] = updatedDotnetSdkVersion;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
}
private async Task> DetermineVersion(string name, string workingDirectory, Regex regex, string program, string command)
@@ -1126,7 +1170,7 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updating build number from '{lines[BUILD_NUMBER_INDEX]}' to '{buildNumber}'.");
lines[BUILD_NUMBER_INDEX] = buildNumber.ToString();
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
return buildNumber;
}
@@ -1140,13 +1184,12 @@ public sealed partial class UpdateMetadataCommands
Console.WriteLine($"- Updating build time from '{lines[BUILD_TIME_INDEX]}' to '{buildTime}'.");
lines[BUILD_TIME_INDEX] = buildTime;
- await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);
+ await WriteMetadataLinesAsync(pathMetadata, lines);
return buildTime;
}
private sealed record RebuildReleaseState(
string MetadataPath,
- string MetadataContent,
string[] MetadataLines,
string AppVersion,
int BuildNumber,
@@ -1200,6 +1243,14 @@ public sealed partial class UpdateMetadataCommands
[GeneratedRegex("^[0-9a-fA-F]{40,64}$")]
private static partial Regex GitCommitHashRegex();
+ // Matches the category of an MSBuild error, e.g., "): error CS0103:", "MSBUILD : error MSB1009:", or "): error :":
+ [GeneratedRegex(""":\s*error(?:\s+[A-Z]+[0-9]+)?\s*:""")]
+ private static partial Regex DotnetErrorRegex();
+
+ // Matches the label of a Tauri CLI error, which is right-aligned to twelve characters:
+ [GeneratedRegex("""^\s+Error\s""")]
+ private static partial Regex TauriErrorRegex();
+
// Matches one Markdown link. The address may hold one level of parentheses, as Wikipedia addresses do:
[GeneratedRegex("""\[(?[^\[\]]+)\]\((?(?:[^()\s]|\([^()\s]*\))+)\)""")]
private static partial Regex MarkdownLinkRegex();
diff --git a/metadata.txt b/metadata.txt
index 87f044842..4afa201ab 100644
--- a/metadata.txt
+++ b/metadata.txt
@@ -9,4 +9,4 @@
9f102728b59, release
osx-arm64
148.0.7763.0
-0.8.0
\ No newline at end of file
+0.8.0
diff --git a/runtime/build.rs b/runtime/build.rs
index 80a92985a..af6716f8d 100644
--- a/runtime/build.rs
+++ b/runtime/build.rs
@@ -36,8 +36,16 @@ fn main() {
let metadata = include_str!("../metadata.txt");
let mut metadata_lines = metadata.lines().collect::>();
metadata_lines[9] = rid;
- let new_metadata = metadata_lines.join("\n");
- std::fs::write("../metadata.txt", new_metadata).unwrap();
+
+ // Every line ends with a line break, the last one included. The build
+ // script of the .NET side writes the file the same way:
+ let mut new_metadata = metadata_lines.join("\n");
+ new_metadata.push('\n');
+
+ // Write only on a change to avoid unnecessary rewrites:
+ if new_metadata != metadata {
+ std::fs::write("../metadata.txt", new_metadata).unwrap();
+ }
//
// Read the current version and update the