Write UTF-8 BOM for solution files.
Currently the solution file written out by the `sln` command uses a UTF-8 encoding without a BOM. This causes problems when the solution file contains non-ASCII code points because Visual Studio and MSBuild will not use a UTF-8 encoding when reading the solution file if the BOM is omitted. This commit causes the BOM to always be written when writing the solution files. Fixes #8184.
This commit is contained in:
parent
3fe29161af
commit
9671ba1de0
3 changed files with 57 additions and 1 deletions
|
@ -33,6 +33,7 @@ using System.IO;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.DotNet.Cli.Sln.Internal.FileManipulation;
|
using Microsoft.DotNet.Cli.Sln.Internal.FileManipulation;
|
||||||
using Microsoft.DotNet.Tools.Common;
|
using Microsoft.DotNet.Tools.Common;
|
||||||
|
|
||||||
|
@ -211,7 +212,7 @@ namespace Microsoft.DotNet.Cli.Sln.Internal
|
||||||
}
|
}
|
||||||
var sw = new StringWriter();
|
var sw = new StringWriter();
|
||||||
Write(sw);
|
Write(sw);
|
||||||
File.WriteAllText(FullPath, sw.ToString());
|
File.WriteAllText(FullPath, sw.ToString(), Encoding.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Write(TextWriter writer)
|
private void Write(TextWriter writer)
|
||||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.DotNet.Tools.Test.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
@ -554,6 +555,33 @@ EndGlobal
|
||||||
cmd.StdErr.Should().BeEmpty();
|
cmd.StdErr.Should().BeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WhenProjectIsAddedSolutionHasUTF8BOM()
|
||||||
|
{
|
||||||
|
var projectDirectory = TestAssets
|
||||||
|
.Get("TestAppWithEmptySln")
|
||||||
|
.CreateInstance()
|
||||||
|
.WithSourceFiles()
|
||||||
|
.Root
|
||||||
|
.FullName;
|
||||||
|
|
||||||
|
var projectToAdd = "Lib/Lib.csproj";
|
||||||
|
var projectPath = Path.Combine("Lib", "Lib.csproj");
|
||||||
|
var cmd = new DotnetCommand()
|
||||||
|
.WithWorkingDirectory(projectDirectory)
|
||||||
|
.ExecuteWithCapturedOutput($"sln App.sln add {projectToAdd}");
|
||||||
|
cmd.Should().Pass();
|
||||||
|
|
||||||
|
var preamble = Encoding.UTF8.GetPreamble();
|
||||||
|
preamble.Length.Should().Be(3);
|
||||||
|
using (var stream = new FileStream(Path.Combine(projectDirectory, "App.sln"), FileMode.Open))
|
||||||
|
{
|
||||||
|
var bytes = new byte[preamble.Length];
|
||||||
|
stream.Read(bytes, 0, bytes.Length);
|
||||||
|
bytes.Should().BeEquivalentTo(preamble);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("TestAppWithSlnAndCsprojFiles")]
|
[InlineData("TestAppWithSlnAndCsprojFiles")]
|
||||||
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
|
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles")]
|
||||||
|
|
|
@ -8,6 +8,7 @@ using Microsoft.DotNet.Tools.Test.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.Cli.Sln.Remove.Tests
|
namespace Microsoft.DotNet.Cli.Sln.Remove.Tests
|
||||||
|
@ -590,6 +591,32 @@ EndGlobal
|
||||||
.Count().Should().Be(1, $"App {reasonString}");
|
.Count().Should().Be(1, $"App {reasonString}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WhenProjectIsRemovedSolutionHasUTF8BOM()
|
||||||
|
{
|
||||||
|
var projectDirectory = TestAssets
|
||||||
|
.Get("TestAppWithSlnAndCsprojToRemove")
|
||||||
|
.CreateInstance()
|
||||||
|
.WithSourceFiles()
|
||||||
|
.Root
|
||||||
|
.FullName;
|
||||||
|
|
||||||
|
var projectToRemove = Path.Combine("Lib", "Lib.csproj");
|
||||||
|
var cmd = new DotnetCommand()
|
||||||
|
.WithWorkingDirectory(projectDirectory)
|
||||||
|
.ExecuteWithCapturedOutput($"sln App.sln remove {projectToRemove}");
|
||||||
|
cmd.Should().Pass();
|
||||||
|
|
||||||
|
var preamble = Encoding.UTF8.GetPreamble();
|
||||||
|
preamble.Length.Should().Be(3);
|
||||||
|
using (var stream = new FileStream(Path.Combine(projectDirectory, "App.sln"), FileMode.Open))
|
||||||
|
{
|
||||||
|
var bytes = new byte[preamble.Length];
|
||||||
|
stream.Read(bytes, 0, bytes.Length);
|
||||||
|
bytes.Should().BeEquivalentTo(preamble);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void WhenFinalReferenceIsRemovedEmptySectionsAreRemoved()
|
public void WhenFinalReferenceIsRemovedEmptySectionsAreRemoved()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue