From 11d65892219967f5522a92bec8f10b72d8c7427d Mon Sep 17 00:00:00 2001 From: webdevred <148627186+webdevred@users.noreply.github.com> Date: Sat, 15 Aug 2026 16:32:13 +0200 Subject: [PATCH] Drop the CRLF conversion and cover the CRLF path with a fixture Converting the shipped examples buys nothing measurable: the rulesets parse identically either way, the tool already keeps the line endings a user's own file came with, and BeamNG ships 150 LF files of 4943 itself. Meanwhile no fixture had a carriage return in it, so the suite never exercised CRLF on a format whose real files mostly are. --- .gitattributes | 11 +++++++ .github/scripts/replace_newlines.sh | 3 -- .github/workflows/build-and-release.yaml | 3 -- examples/README.md | 8 +++++ .../regression_jbeam/crlf-line-endings.jbeam | 25 +++++++++++++++ jbeam-edit.cabal | 1 + test/CrlfSpec.hs | 32 +++++++++++++++++++ 7 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 .gitattributes delete mode 100644 .github/scripts/replace_newlines.sh create mode 100644 examples/regression_jbeam/crlf-line-endings.jbeam create mode 100644 test/CrlfSpec.hs diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..b46c9ad1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# The repository stores LF. Windows checkouts convert on the way in and out, +# which is fine for everything except the two cases below. +* text=auto + +# Bash refuses to run a script with carriage returns. +*.sh text eol=lf + +# Deliberately CRLF, and pinned as binary so no checkout or commit normalises +# it away. Real BeamNG files are overwhelmingly CRLF and every other fixture +# here is LF, so this is the only one that exercises that path. +examples/regression_jbeam/crlf-line-endings.jbeam -text diff --git a/.github/scripts/replace_newlines.sh b/.github/scripts/replace_newlines.sh deleted file mode 100644 index 00c4c242..00000000 --- a/.github/scripts/replace_newlines.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -find examples/formatted_jbeam examples/transformed_jbeam -type f -exec sed -i 's/$/\r/' {} + diff --git a/.github/workflows/build-and-release.yaml b/.github/workflows/build-and-release.yaml index dbecf4e3..d3d570fa 100644 --- a/.github/workflows/build-and-release.yaml +++ b/.github/workflows/build-and-release.yaml @@ -97,9 +97,6 @@ jobs: run: | echo "Running benchmarks for jbeam-edit" cabal bench --project-file cabal.project.release --benchmark-options="--verbosity=1" - - name: Enforce CRLF newlines on windows - run: bash ./.github/scripts/replace_newlines.sh - shell: bash - name: Test executable shell: bash run: bash ./.github/scripts/prepare_installer.sh diff --git a/examples/README.md b/examples/README.md index a03b431b..b939677c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -143,6 +143,14 @@ The yaml configuration file allows the user to configure custom transformation s **File:** `examples/jbeam-edit.yaml` +## Line endings + +These files use LF, while most files that ship with BeamNG use CRLF. Nothing +breaks either way. jbeam-edit reads both, and formatting a `.jbeam` file keeps +whichever line endings that file already had, so your own files are untouched. +BeamNG itself is not consistent about it: 150 of the 4943 jbeam files in the +stock vehicles are LF. + --- For complete documentation, refer to the root [README.md](../README.md). diff --git a/examples/regression_jbeam/crlf-line-endings.jbeam b/examples/regression_jbeam/crlf-line-endings.jbeam new file mode 100644 index 00000000..9ac469b8 --- /dev/null +++ b/examples/regression_jbeam/crlf-line-endings.jbeam @@ -0,0 +1,25 @@ +{ +"testpart":{ + "nodes":[ + ["id", "posX", "posY", "posZ"], + // Synthetic regression-test fixture, not vetted by the jbeam + // maintainer and not intended as a demo/example. + // + // Stored with CRLF line endings on purpose, and pinned as binary in + // .gitattributes so no checkout or commit converts them away. 4793 of + // the 4943 jbeam files in the stock vehicles are CRLF, and every other + // fixture here is LF, so without this one the parser only ever sees LF. + /* + A block comment, because the parser has had a CRLF-specific bug in one + of these before. + */ + {"nodeWeight":1.0}, + ["nl0", 0.9, -1.0, 0.1], + ["nl1", 0.9, 0.0, 0.1, {"group":"test"}], + ], + "beams":[ + ["id1:", "id2:"], + ["nl0", "nl1"], + ], +}, +} diff --git a/jbeam-edit.cabal b/jbeam-edit.cabal index c101eea4..1e216a49 100644 --- a/jbeam-edit.cabal +++ b/jbeam-edit.cabal @@ -264,6 +264,7 @@ test-suite jbeam-edit-test Core.NodeCursorSpec Core.NodePathSpec Core.NodeSpec + CrlfSpec Formatting.RulesSpec FormattingSpec Parsing.DSLSpec diff --git a/test/CrlfSpec.hs b/test/CrlfSpec.hs new file mode 100644 index 00000000..46179e1a --- /dev/null +++ b/test/CrlfSpec.hs @@ -0,0 +1,32 @@ +module CrlfSpec (spec) where + +import Data.ByteString.Lazy qualified as LBS +import Data.Either (isRight) +import JbeamEdit.Parsing.Jbeam (parseNodes) +import Test.Hspec + +carriageReturn :: LBS.ByteString -> Bool +carriageReturn = LBS.elem 13 + +{- | Line endings are the file's business, not the content's, so the same file +read as CRLF and as LF has to parse to the same tree. Every other fixture here +is LF while 4793 of the 4943 jbeam files in the stock vehicles are CRLF, so +without this one the ordinary suite never sees a carriage return at all, and +the parser has had a CRLF-specific bug in a block comment before. +-} +spec :: Spec +spec = do + crlf <- runIO $ LBS.readFile "examples/regression_jbeam/crlf-line-endings.jbeam" + let lf = LBS.filter (/= 13) crlf + describe "a jbeam file with CRLF line endings" $ do + it "still has its carriage returns" $ + -- Guards against a checkout or a .gitattributes change quietly + -- normalising the fixture, which would leave the rest passing vacuously. + crlf `shouldSatisfy` carriageReturn + + it "parses to the same tree as the same file with LF" $ do + lf `shouldNotSatisfy` carriageReturn + parseNodes crlf `shouldBe` parseNodes lf + + it "parses at all" $ + parseNodes crlf `shouldSatisfy` isRight