Skip to content

Commit eeaeb1a

Browse files
Normalize CRLF to LF in text files for cross-platform determinism
Strip \r\n → \n for non-binary files (skip .png and .usm) so that archives are byte-identical regardless of git line ending settings on the build machine. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f834cce commit eeaeb1a

2 files changed

Lines changed: 22 additions & 4 deletions

File tree

.github/workflows/determinism.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
run: dotnet --info
2727

2828
- name: Clone test data
29-
run: git clone --depth 1 -c core.autocrlf=false -c core.eol=lf https://github.com/MS2Community/MapleStory2-XML.git test-data
29+
run: git clone --depth 1 https://github.com/MS2Community/MapleStory2-XML.git test-data
3030

3131
- name: Build
3232
run: dotnet build MS2Tools.sln -c Release

MS2Create/Program.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,32 @@ private static void AddAndCreateFileToArchive(IMS2Archive archive, (string fullP
9191
(string filePath, string relativePath) = filePaths[index];
9292

9393
uint id = index + 1;
94-
FileStream fsFile = File.OpenRead(filePath);
94+
Stream dataStream = OpenNormalized(filePath);
9595
IMS2FileInfo info = new MS2FileInfo(id.ToString(), relativePath);
96-
IMS2FileHeader header = new MS2FileHeader(fsFile.Length, id, 0, GetCompressionTypeFromFileExtension(filePath));
97-
IMS2File file = new MS2File(archive, fsFile, info, header, false);
96+
IMS2FileHeader header = new MS2FileHeader(dataStream.Length, id, 0, GetCompressionTypeFromFileExtension(filePath));
97+
IMS2File file = new MS2File(archive, dataStream, info, header, false);
9898

9999
archive.Add(file);
100100
}
101101

102+
private static Stream OpenNormalized(string filePath) {
103+
CompressionType ct = GetCompressionTypeFromFileExtension(filePath);
104+
if (ct == CompressionType.Png || ct == CompressionType.Usm) {
105+
return File.OpenRead(filePath);
106+
}
107+
108+
byte[] raw = File.ReadAllBytes(filePath);
109+
int dst = 0;
110+
for (int src = 0; src < raw.Length; src++) {
111+
if (raw[src] == (byte)'\r' && src + 1 < raw.Length && raw[src + 1] == (byte)'\n') {
112+
continue;
113+
}
114+
raw[dst++] = raw[src];
115+
}
116+
117+
return new MemoryStream(raw, 0, dst, writable: false);
118+
}
119+
102120
private static (string FullPath, string RelativePath)[] GetFilesRelative(string path) {
103121
if (!path.EndsWith(Path.DirectorySeparatorChar)) {
104122
path += Path.DirectorySeparatorChar;

0 commit comments

Comments
 (0)