Skip to content

tests/android_tests/gradlew.bat is dirty in every fresh clone (*.bat text eol=crlf vs LF blob) — breaks rive-ios SPM submodule resolution in Xcode #120

Open

Description

@bulam

Summary

tests/android_tests/gradlew.bat shows as modified in every fresh clone of this repo. The root .gitattributes declares *.bat text eol=crlf, but the blob is stored LF-normalized — with that combination, git writes CRLF into the working tree at checkout and immediately reports the path as dirty ("warning: in the working copy of 'tests/android_tests/gradlew.bat', LF will be replaced by CRLF the next time Git touches it").

Repro

$ git clone https://github.com/rive-app/rive-runtime && cd rive-runtime
$ git status --porcelain
 M tests/android_tests/gradlew.bat

Minimal isolated repro of the mechanism (git 2.50.1):

$ git init repo && cd repo
$ printf '*.bat text eol=crlf\n' > .gitattributes
$ printf '@rem\n@rem test\n' > gradlew.bat        # LF endings, like the committed blob
$ git add -A && git commit -m init
$ cd .. && git clone repo clone && git -C clone status --porcelain
 M gradlew.bat

Note git add --renormalize stages nothing (the blob is already LF), so the dirt can't be cleaned up by renormalizing — every clone is dirty by construction until the attribute changes.

Why it matters downstream

rive-ios embeds this repo as a git submodule, and Swift Package Manager clones it into Xcode's DerivedData/.../SourcePackages/checkouts/. The perpetually-dirty submodule breaks SPM package resolution — Xcode surfaces it as "Failed to analyze workspace", and a rive-ios version bump fails to resolve until the checkout is manually repaired. (Observed with rive-ios 6.22.0, Xcode 26.x.)

Suggested fix

Exempt the wrapper script from text normalization so the working tree is byte-identical to the blob, e.g. in .gitattributes:

tests/android_tests/gradlew.bat -text

(Optionally re-commit the file with CRLF endings at the same time if CRLF-on-disk is desired for Windows — with -text git no longer converts either way. gradle init's own generated .gitattributes handles it this way.)

Workaround for consumers

Add the override to a global attributes file so all checkouts (including SPM's) stay clean:

$ printf 'tests/android_tests/gradlew.bat -text\n' >> ~/.config/git/attributes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions