What's wrong
KtsuTools.Packages/PackagesService.cs reads project files with File.ReadAllTextAsync, which drops the byte-order mark. It writes them back with File.WriteAllTextAsync, whose default is UTF-8 without a BOM. This happens in:
UpdatePackageVersionInFileAsync, around L404, used by packages update;
MergePackagesPropsAsync, around L533, used by packages migrate-cpm when a Directory.Packages.props already exists.
SerializeLikeOriginal restores the XML declaration and line endings, but not the encoding preamble.
Reproduced at HEAD 3908181. A csproj beginning EF BB BF 3C 50 72 … (BOM + <Pr) starts with 3C 50 72 after UpdatePackageVersionInFileAsync(path, "X", "2.0.0").
Why it matters
#194 was fixed so that project files are written back "as they were". Visual Studio creates csproj and props files with a BOM by default, so every packages update run still produces a whole-file encoding change in the diff alongside the one-line version bump.
Related issues:
Suggested fix
Detect the encoding when reading and write back with the same one. For example, read with a StreamReader(detectEncodingFromByteOrderMarks: true) and keep CurrentEncoding, or check for the 3-byte preamble and write with new UTF8Encoding(encoderShouldEmitUTF8Identifier: hadBom). A shared helper could serve #213 and #209 too.
Acceptance criteria
- A csproj with a BOM and CRLF line endings, run through
packages update, is byte-identical afterwards apart from the changed Version attribute.
- The same holds for a
Directory.Packages.props merged by migrate-cpm.
- Files without a BOM stay without one.
What's wrong
KtsuTools.Packages/PackagesService.csreads project files withFile.ReadAllTextAsync, which drops the byte-order mark. It writes them back withFile.WriteAllTextAsync, whose default is UTF-8 without a BOM. This happens in:UpdatePackageVersionInFileAsync, around L404, used bypackages update;MergePackagesPropsAsync, around L533, used bypackages migrate-cpmwhen aDirectory.Packages.propsalready exists.SerializeLikeOriginalrestores the XML declaration and line endings, but not the encoding preamble.Reproduced at HEAD 3908181. A csproj beginning
EF BB BF 3C 50 72 …(BOM +<Pr) starts with3C 50 72afterUpdatePackageVersionInFileAsync(path, "X", "2.0.0").Why it matters
#194 was fixed so that project files are written back "as they were". Visual Studio creates csproj and props files with a BOM by default, so every
packages updaterun still produces a whole-file encoding change in the diff alongside the one-line version bump.Related issues:
packages migrate-cpmdrops the XML declaration and converts CRLF to LF in every csproj, and misses<Version>child elements #213 covers migrate-cpm's csproj rewrite losing the declaration and CRLF, but doesn't mention the BOM or these two code paths.mergesubcommand.Suggested fix
Detect the encoding when reading and write back with the same one. For example, read with a
StreamReader(detectEncodingFromByteOrderMarks: true)and keepCurrentEncoding, or check for the 3-byte preamble and write withnew UTF8Encoding(encoderShouldEmitUTF8Identifier: hadBom). A shared helper could serve #213 and #209 too.Acceptance criteria
packages update, is byte-identical afterwards apart from the changedVersionattribute.Directory.Packages.propsmerged bymigrate-cpm.