зеркало из https://github.com/dotnet/msbuild.git
Live logger properly report errors during restore. (#8707)
Fixes #8704 Context Errors during restore was not reported when using /tl (live logger) leaving user without actionable information. Changes Made When restore success without error or warn - same as before When restore success with warnings - report success with warnins and list warnings bellow that report When restore fails - report errors and warnings THEN report Restore failed in 1.5s and do not report Build summary
This commit is contained in:
Родитель
6882ab9de1
Коммит
b313662f92
|
@ -4,6 +4,8 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Logging.LiveLogger;
|
||||
using Shouldly;
|
||||
|
@ -182,7 +184,7 @@ namespace Microsoft.Build.UnitTests
|
|||
public void PrintsBuildSummary_Succeeded()
|
||||
{
|
||||
InvokeLoggerCallbacksForSimpleProject(succeeded: true, () => { });
|
||||
_mockTerminal.GetLastLine().ShouldBe("Build succeeded in 5.0s");
|
||||
_mockTerminal.GetLastLine().WithoutAnsiCodes().ShouldBe("Build succeeded in 5.0s");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -192,14 +194,14 @@ namespace Microsoft.Build.UnitTests
|
|||
{
|
||||
WarningRaised?.Invoke(_eventSender, MakeWarningEventArgs("Warning!"));
|
||||
});
|
||||
_mockTerminal.GetLastLine().ShouldBe("Build succeeded with warnings in 5.0s");
|
||||
_mockTerminal.GetLastLine().WithoutAnsiCodes().ShouldBe("Build succeeded with warnings in 5.0s");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PrintBuildSummary_Failed()
|
||||
{
|
||||
InvokeLoggerCallbacksForSimpleProject(succeeded: false, () => { });
|
||||
_mockTerminal.GetLastLine().ShouldBe("Build failed in 5.0s");
|
||||
_mockTerminal.GetLastLine().WithoutAnsiCodes().ShouldBe("Build failed in 5.0s");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -209,9 +211,20 @@ namespace Microsoft.Build.UnitTests
|
|||
{
|
||||
ErrorRaised?.Invoke(_eventSender, MakeErrorEventArgs("Error!"));
|
||||
});
|
||||
_mockTerminal.GetLastLine().ShouldBe("Build failed with errors in 5.0s");
|
||||
_mockTerminal.GetLastLine().WithoutAnsiCodes().ShouldBe("Build failed with errors in 5.0s");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
internal static class StringVT100Extensions
|
||||
{
|
||||
private static Regex s_removeAnsiCodes = new Regex("\\x1b\\[[0-9;]*[mGKHF]");
|
||||
|
||||
public static string WithoutAnsiCodes(this string text)
|
||||
{
|
||||
return s_removeAnsiCodes.Replace(text, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,6 @@ namespace Microsoft.Build.UnitTests
|
|||
public void Write(ReadOnlySpan<char> text) { AddOutput(text.ToString()); }
|
||||
public void WriteColor(TerminalColor color, string text) => AddOutput(text);
|
||||
public void WriteColorLine(TerminalColor color, string text) { AddOutput(text); AddOutput("\n"); }
|
||||
public string RenderColor(TerminalColor color, string text) => text;
|
||||
|
||||
public void WriteLine(string text) { AddOutput(text); AddOutput("\n"); }
|
||||
public void WriteLineFitToWidth(ReadOnlySpan<char> text)
|
||||
|
|
|
@ -63,9 +63,4 @@ internal interface ITerminal : IDisposable
|
|||
/// Writes a string to the output using the given color. Or buffers it if <see cref="BeginUpdate"/> was called.
|
||||
/// </summary>
|
||||
void WriteColorLine(TerminalColor color, string text);
|
||||
|
||||
/// <summary>
|
||||
/// Return string representing text wrapped in VT100 color codes.
|
||||
/// </summary>
|
||||
string RenderColor(TerminalColor color, string text);
|
||||
}
|
||||
|
|
|
@ -109,6 +109,11 @@ internal sealed class LiveLogger : INodeLogger
|
|||
/// </summary>
|
||||
private bool _buildHasWarnings;
|
||||
|
||||
/// <summary>
|
||||
/// True if restore failed and this failure has already been reported.
|
||||
/// </summary>
|
||||
private bool _restoreFailed;
|
||||
|
||||
/// <summary>
|
||||
/// The project build context corresponding to the <c>Restore</c> initial target, or null if the build is currently
|
||||
/// bot restoring.
|
||||
|
@ -235,12 +240,22 @@ internal sealed class LiveLogger : INodeLogger
|
|||
Terminal.BeginUpdate();
|
||||
try
|
||||
{
|
||||
double duration = (e.Timestamp - _buildStartTime).TotalSeconds;
|
||||
string duration = (e.Timestamp - _buildStartTime).TotalSeconds.ToString("F1");
|
||||
string buildResult = RenderBuildResult(e.Succeeded, _buildHasErrors, _buildHasWarnings);
|
||||
|
||||
Terminal.WriteLine("");
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("BuildFinished",
|
||||
RenderBuildResult(e.Succeeded, _buildHasErrors, _buildHasWarnings),
|
||||
duration.ToString("F1")));
|
||||
if (_restoreFailed)
|
||||
{
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("RestoreCompleteWithMessage",
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
else
|
||||
{
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("BuildFinished",
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -249,6 +264,7 @@ internal sealed class LiveLogger : INodeLogger
|
|||
|
||||
_buildHasErrors = false;
|
||||
_buildHasWarnings = false;
|
||||
_restoreFailed = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -302,35 +318,7 @@ internal sealed class LiveLogger : INodeLogger
|
|||
|
||||
ProjectContext c = new(buildEventContext);
|
||||
|
||||
// First check if we're done restoring.
|
||||
if (_restoreContext is ProjectContext restoreContext && c == restoreContext)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_restoreContext = null;
|
||||
|
||||
Stopwatch projectStopwatch = _projects[restoreContext].Stopwatch;
|
||||
double duration = projectStopwatch.Elapsed.TotalSeconds;
|
||||
projectStopwatch.Stop();
|
||||
|
||||
Terminal.BeginUpdate();
|
||||
try
|
||||
{
|
||||
EraseNodes();
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("RestoreComplete",
|
||||
duration.ToString("F1")));
|
||||
DisplayNodes();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Terminal.EndUpdate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If this was a notable project build, we print it as completed only if it's produced an output or warnings/error.
|
||||
if (_projects.TryGetValue(c, out Project? project) && (project.OutputPath is not null || project.BuildMessages is not null))
|
||||
if (_projects.TryGetValue(c, out Project? project))
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
|
@ -350,65 +338,97 @@ internal sealed class LiveLogger : INodeLogger
|
|||
// reported during build.
|
||||
bool haveErrors = project.BuildMessages?.Exists(m => m.Severity == MessageSeverity.Error) == true;
|
||||
bool haveWarnings = project.BuildMessages?.Exists(m => m.Severity == MessageSeverity.Warning) == true;
|
||||
|
||||
string buildResult = RenderBuildResult(e.Succeeded, haveErrors, haveWarnings);
|
||||
|
||||
if (string.IsNullOrEmpty(project.TargetFramework))
|
||||
// Check if we're done restoring.
|
||||
if (c == _restoreContext)
|
||||
{
|
||||
Terminal.Write(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ProjectFinished_NoTF",
|
||||
Indentation,
|
||||
projectFile,
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
else
|
||||
{
|
||||
Terminal.Write(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ProjectFinished_WithTF",
|
||||
Indentation,
|
||||
projectFile,
|
||||
AnsiCodes.Colorize(project.TargetFramework, TargetFrameworkColor),
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
|
||||
// Print the output path as a link if we have it.
|
||||
if (outputPath is not null)
|
||||
{
|
||||
ReadOnlySpan<char> outputPathSpan = outputPath.Value.Span;
|
||||
ReadOnlySpan<char> url = outputPathSpan;
|
||||
try
|
||||
if (e.Succeeded)
|
||||
{
|
||||
// If possible, make the link point to the containing directory of the output.
|
||||
url = Path.GetDirectoryName(url);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any GetDirectoryName exceptions.
|
||||
}
|
||||
|
||||
// Generates file:// schema url string which is better handled by various Terminal clients than raw folder name.
|
||||
string urlString = url.ToString();
|
||||
if (Uri.TryCreate(urlString, UriKind.Absolute, out Uri? uri))
|
||||
{
|
||||
urlString = uri.AbsoluteUri;
|
||||
}
|
||||
|
||||
// If the output path is under the initial working directory, make the console output relative to that to save space.
|
||||
if (outputPathSpan.StartsWith(_initialWorkingDirectory.AsSpan(), FileUtilities.PathComparison))
|
||||
{
|
||||
if (outputPathSpan.Length > _initialWorkingDirectory.Length
|
||||
&& (outputPathSpan[_initialWorkingDirectory.Length] == Path.DirectorySeparatorChar
|
||||
|| outputPathSpan[_initialWorkingDirectory.Length] == Path.AltDirectorySeparatorChar))
|
||||
if (haveErrors || haveWarnings)
|
||||
{
|
||||
outputPathSpan = outputPathSpan.Slice(_initialWorkingDirectory.Length + 1);
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("RestoreCompleteWithMessage",
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
else
|
||||
{
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("RestoreComplete",
|
||||
duration));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It will be reported after build finishes.
|
||||
_restoreFailed = true;
|
||||
}
|
||||
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ProjectFinished_OutputPath",
|
||||
$"{AnsiCodes.LinkPrefix}{urlString}{AnsiCodes.LinkInfix}{outputPathSpan.ToString()}{AnsiCodes.LinkSuffix}"));
|
||||
_restoreContext = null;
|
||||
}
|
||||
else
|
||||
// If this was a notable project build, we print it as completed only if it's produced an output or warnings/error.
|
||||
else if (project.OutputPath is not null || project.BuildMessages is not null)
|
||||
{
|
||||
Terminal.WriteLine(string.Empty);
|
||||
// Show project build complete and its output
|
||||
|
||||
if (string.IsNullOrEmpty(project.TargetFramework))
|
||||
{
|
||||
Terminal.Write(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ProjectFinished_NoTF",
|
||||
Indentation,
|
||||
projectFile,
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
else
|
||||
{
|
||||
Terminal.Write(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ProjectFinished_WithTF",
|
||||
Indentation,
|
||||
projectFile,
|
||||
AnsiCodes.Colorize(project.TargetFramework, TargetFrameworkColor),
|
||||
buildResult,
|
||||
duration));
|
||||
}
|
||||
|
||||
// Print the output path as a link if we have it.
|
||||
if (outputPath is not null)
|
||||
{
|
||||
ReadOnlySpan<char> outputPathSpan = outputPath.Value.Span;
|
||||
ReadOnlySpan<char> url = outputPathSpan;
|
||||
try
|
||||
{
|
||||
// If possible, make the link point to the containing directory of the output.
|
||||
url = Path.GetDirectoryName(url);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore any GetDirectoryName exceptions.
|
||||
}
|
||||
|
||||
// Generates file:// schema url string which is better handled by various Terminal clients than raw folder name.
|
||||
string urlString = url.ToString();
|
||||
if (Uri.TryCreate(urlString, UriKind.Absolute, out Uri? uri))
|
||||
{
|
||||
urlString = uri.AbsoluteUri;
|
||||
}
|
||||
|
||||
// If the output path is under the initial working directory, make the console output relative to that to save space.
|
||||
if (outputPathSpan.StartsWith(_initialWorkingDirectory.AsSpan(), FileUtilities.PathComparison))
|
||||
{
|
||||
if (outputPathSpan.Length > _initialWorkingDirectory.Length
|
||||
&& (outputPathSpan[_initialWorkingDirectory.Length] == Path.DirectorySeparatorChar
|
||||
|| outputPathSpan[_initialWorkingDirectory.Length] == Path.AltDirectorySeparatorChar))
|
||||
{
|
||||
outputPathSpan = outputPathSpan.Slice(_initialWorkingDirectory.Length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Terminal.WriteLine(ResourceUtilities.FormatResourceStringIgnoreCodeAndKeyword("ProjectFinished_OutputPath",
|
||||
$"{AnsiCodes.LinkPrefix}{urlString}{AnsiCodes.LinkInfix}{outputPathSpan.ToString()}{AnsiCodes.LinkSuffix}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Terminal.WriteLine(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
// Print diagnostic output under the Project -> Output line.
|
||||
|
@ -762,15 +782,15 @@ internal sealed class LiveLogger : INodeLogger
|
|||
(false, true) => ResourceUtilities.GetResourceString("BuildResult_FailedWithWarnings"),
|
||||
_ => ResourceUtilities.GetResourceString("BuildResult_Failed"),
|
||||
};
|
||||
return Terminal.RenderColor(TerminalColor.Red, text);
|
||||
return AnsiCodes.Colorize(text, TerminalColor.Red);
|
||||
}
|
||||
else if (hasWarning)
|
||||
{
|
||||
return Terminal.RenderColor(TerminalColor.Yellow, ResourceUtilities.GetResourceString("BuildResult_SucceededWithWarnings"));
|
||||
return AnsiCodes.Colorize(ResourceUtilities.GetResourceString("BuildResult_SucceededWithWarnings"), TerminalColor.Yellow);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Terminal.RenderColor(TerminalColor.Green, ResourceUtilities.GetResourceString("BuildResult_Succeeded"));
|
||||
return AnsiCodes.Colorize(ResourceUtilities.GetResourceString("BuildResult_Succeeded"), TerminalColor.Green);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,16 +132,10 @@ internal sealed class Terminal : ITerminal
|
|||
}
|
||||
else
|
||||
{
|
||||
Write(RenderColor(color, text));
|
||||
Write(AnsiCodes.Colorize(text, color));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string RenderColor(TerminalColor color, string text)
|
||||
{
|
||||
return $"{AnsiCodes.CSI}{(int)color}{AnsiCodes.SetColor}{text}{AnsiCodes.SetDefaultColor}";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void WriteColorLine(TerminalColor color, string text)
|
||||
{
|
||||
|
|
|
@ -1373,6 +1373,14 @@
|
|||
{0}: duration in seconds with 1 decimal point
|
||||
</comment>
|
||||
</data>
|
||||
<data name="RestoreCompleteWithMessage" xml:space="preserve">
|
||||
<value>Restore {0} in {1}s</value>
|
||||
<comment>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</comment>
|
||||
</data>
|
||||
<data name="BuildFinished" xml:space="preserve">
|
||||
<value>Build {0} in {1}s</value>
|
||||
<comment>
|
||||
|
|
|
@ -1484,6 +1484,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1476,6 +1476,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1483,6 +1483,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1476,6 +1476,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1487,6 +1487,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1476,6 +1476,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1476,6 +1476,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1485,6 +1485,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1477,6 +1477,15 @@ arquivo de resposta.
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1475,6 +1475,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1480,6 +1480,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1476,6 +1476,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
|
@ -1476,6 +1476,15 @@
|
|||
<target state="new">Restore complete ({0}s)</target>
|
||||
<note>
|
||||
{0}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="RestoreCompleteWithMessage">
|
||||
<source>Restore {0} in {1}s</source>
|
||||
<target state="new">Restore {0} in {1}s</target>
|
||||
<note>
|
||||
Restore summary when finished with warning or error
|
||||
{0}: BuildResult_X (below)
|
||||
{1}: duration in seconds with 1 decimal point
|
||||
</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="SchemaFileLocation">
|
||||
|
|
Загрузка…
Ссылка в новой задаче