l3build icon indicating copy to clipboard operation
l3build copied to clipboard

CRLF is still used as EOL in Windows

Open muzimuzhi opened this issue 1 year ago • 11 comments

Currently when run in Windows, l3build save still uses CRLF as end-of-line in generated .tlg, despite the existing EOL normalizations in rewrite() (line 95 below) https://github.com/latex3/l3build/blob/2c9e1785b7ae3c989cf567c89f9cf6a35b5d4fc9/l3build-check.lua#L93-L102

This brings inconvenience to the cooperation between Win and non-Win users, see for example https://github.com/lvjr/tabularray/pull/385#issuecomment-1474855272.

I did some tests in https://github.com/muzimuzhi/hello-github-actions/pull/6 and found

  • it's io.write() that converts \n to \r\n automatically in Windows and
  • it seems opening the file in binary mode (open(source, "rb")) does the trick.

muzimuzhi avatar Mar 19 '23 05:03 muzimuzhi

I'm not following here. Saved .tlg files should have the right line endings for the platform being used, so CRLF for Windows. That's what happens as far as I know, and it works fine for us (@u-fischer always uses Windows, I have a mixed setup, others only using *nix). What behaviour are you expecting that's different from the present situation?

josephwright avatar Mar 20 '23 07:03 josephwright

@josephwright I think the problem depends on how you configure your source control. if git checks out local files with windows line endings you want to save tlg with windows endings but if you configure git to not convert then you want to write the same (nix) format on all platforms otherwise files saved on windows have crnl in the repo and fail on the CI

davidcarlisle avatar Mar 20 '23 07:03 davidcarlisle

@davidcarlisle But isn't that the same as any other method where you've decided not to follow the system setting: managing line endings is down to you? I'm not sure how l3build is supposed to know to do anything non-standard - it's not dependent on the development set-up per se rather the choice of an individual when getting a set of files.

josephwright avatar Mar 20 '23 08:03 josephwright

@josephwright not sure either is "non standard" git (like svn and cvs before it) have a boolean option to translate or not line ends. Certainly here we configure source control not to change line endings (which really messes things up if you have a shared file system) l3build would know if it had a boolean option settable in build.lua saveusinglocaleol=false or whatever.

davidcarlisle avatar Mar 20 '23 09:03 davidcarlisle

@josephwright not sure either is "non standard" git (like svn and cvs before it) have a boolean option to translate or not line ends. Certainly here we configure source control not to change line endings (which really messes things up if you have a shared file system) l3build would know if it had a boolean option settable in build.lua saveusinglocaleol=false or whatever.

I meant 'non-standard' as in 'not what the system plain text editor would do' (so Notepad on Windows, TextEdit on macOS, various possibles for Linux).

My worry with a control variable is it suggests the behaviour depends on the module development code, whereas it depends on the practice of the person working on the code. So it's really 'machine-dependent'.

josephwright avatar Mar 20 '23 11:03 josephwright

correct me if I'm wrong, but assuming there would be a control variable test-linefeed-behavior, say, and it would accept the values system, lf, crlf, cr then regardless of what I set them to, save and check on a single system should work just fine. What it does if a source control system comes into play then depends on how I set that up and I have to make sure that the setting works together. And it should also work fine if you have a shared file system to store the stuff and developers on different platforms would use save/check as long as all of them set the variable to the same setting (other than "system").

FrankMittelbach avatar Mar 20 '23 11:03 FrankMittelbach

@josephwright well yes it's come up before that some settings might want to be personal and set from lua outside the repo (upload emails etc) But an option that is not always right seems better than a fixed setting that's always wrong (on windows with core.autocrlf off) a build.lua for a project with users with different settings could set the option after testing git config --get core.autocrlf .

Currently if the checked in files have \n line endings and you save on windows you get the "wrong" endings and rely on git to further normalise on commit.

davidcarlisle avatar Mar 20 '23 11:03 davidcarlisle

Well if the general feeling is it makes sense, I will of course sort it. I guess do a last-minute replacement of \n with <requested-ended> and use rb. So probably don't use a switch but rather a var which defaults to the system default?

josephwright avatar Mar 21 '23 06:03 josephwright

Hmm I kinda changed my idea.

It seems by convention either inherited or system default EOLs are used by programs generating files that would be tracked by a version control software, and setting .gitattributes is a (if not "the") recommended solution, for example latex package author can add *.tlg text eol=lf to .gitattributes.

I consulted two front-end tools, `babel` and `npm`.

  • From a babel issue opened in Oct 2018,

    Babel doesn't keep any whitespace information around after the file is parsed. In general we're reducing the amount of control over output formatting that we expose, because all we really want to guarantee is that the file we output will run properly, and CR/LF values don't affect that. https://github.com/babel/babel/issues/8921#issuecomment-432715372

    We likely preserve CRLF in the output for literal tokens that contained newlines in the original source, like if you have CRLF in a comment or a template literal and don't transform them somehow, I think they would pass through with CRLF values still. https://github.com/babel/babel/issues/8921#issuecomment-433283009

  • From a npm PR opened and merged in Feb 2018,

    This also improves performance on Unix systems since it avoids replacing newlines when it's not necessary.

    Tests have been added to test that package[-lock].json files are written to disk with their original line endings. https://github.com/npm/npm/pull/19907

In the sense of inheritance, l3build may also be requested to respect existing EOLs in each test output when saving new outputs (so the first wins). Then adding a new variable (as suggested in current issue) to do project-wide control looks easier and more efficient.

muzimuzhi avatar Mar 23 '23 04:03 muzimuzhi

Supporting info: Code formatter prettier has an option endOfLine: "<lf|crlf|cr|auto>" with default value lf. https://prettier.io/docs/en/options.html#end-of-line

muzimuzhi avatar Mar 27 '23 11:03 muzimuzhi

Looking back, I think handling this with some 'local config' makes sense, but I wonder how we make sure such a file can only be used for appropriate variables, e.g. yes for line ending but no for anything repo-dependent.

josephwright avatar Jul 16 '23 19:07 josephwright