You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Every writer that splices into a text file has to answer one question: "which line terminator does this file use?" On main @ 045d7ec the crate answers it with five different rules, plus about a dozen inline copies:
Uniform files are safe: every rule agrees on an LF-only or CRLF-only file, which is what git autocrlf produces. The risk is on mixed files (editor merges on Windows), where each new writer picks a rule by copy-paste. That produces churn and broken byte-exact reverts, one bug report per writer. Size: about 25 sites, mostly one-liners.
Target design
utils::line_endings is the only place that classifies terminators:
LineEndings::of (exists);
fn terminator(text) -> &'static str: Crlf → \r\n, Mixed → majority_terminator, otherwise \n. It's stable under appending lines in its own style, so a revert that removes {line}{nl} still finds what the forward pass wrote;
fn restore_rendering(original, rendered): the toml_edit re-expansion, moved from python_lock, with one documented mixed-file rule (per replaced fragment, as Fix Poetry/PDM lock splice drift (#694, #695) #703 does).
Whether a writer refuses a mixed file stays a per-format decision, but it reads the same classifier.
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: register comment.
Kind: tracking. Source: review 4.4 ("CRLF policy is inconsistent"), 5.4 (toml_edit CRLF), 7.3; register E16.
Problem
Every writer that splices into a text file has to answer one question: "which line terminator does this file use?" On main @
045d7ecthe crate answers it with five different rules, plus about a dozen inline copies:\r\n→ CRLFcommon::detect_eol(go.sum, go.mod, requirements, yarn classic); a byte-identical private copy,pypi_uv::newline_of; and inline copies informats/gem/hosted.rs#L65,maven_reactor.rs#L1519,[`#L1776`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/vendor/jvm/maven_reactor.rs#L1776),``upstream/composer.rs#L259,[`upstream/gem.rs#L535`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/patch/redirect/upstream/gem.rs#L535),``upstream/pypi.rs#L629,[`upstream/cargo.rs#L62`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/patch/redirect/upstream/cargo.rs#L62-L63)`` and#L304,``redirect/pipenv.rs#L129, `redirect/npmrc.rs#L614`, `redirect/mod.rs#L5775`, `utils/python_script.rs#L44`gradle::newline_of; yarn classicblock_eol(first line of the block)LineEndings+majority_terminator, used byJsonLayout(common.rs#L217-L222) and composerlock_text.rs#L35-L40``python_lock::preserve_line_endings(15 toml_edit callers in utils, redirect and vendor); hosted cargocrlf_to_lfpnpm_lock.rs#L524); berry refuses mixedThe rules have drifted. A throwaway unit probe on main, run twice, gives three different answers for the same input:
They also disagree within one ecosystem. For Cargo, the hosted rewrite refuses a mixed
Cargo.lock(cargo_mixed_line_endings_still_refuse), but upstream restore LF-normalizes it and re-expands every line to CRLF (upstream/cargo.rs#L62-L63,[`#L155`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/patch/redirect/upstream/cargo.rs#L155)).`` For yarn classic, hosted CRLF-expands the whole file while vendored splices withdetect_eoland reverts withblock_eol(#467).Symptoms
package.jsonloses CRLF (serialize_json), in PR Fix vendored pnpm package.json CRLF/BOM layout (#662) #810.Impact
Uniform files are safe: every rule agrees on an LF-only or CRLF-only file, which is what git
autocrlfproduces. The risk is on mixed files (editor merges on Windows), where each new writer picks a rule by copy-paste. That produces churn and broken byte-exact reverts, one bug report per writer. Size: about 25 sites, mostly one-liners.Target design
utils::line_endingsis the only place that classifies terminators:LineEndings::of(exists);fn terminator(text) -> &'static str:Crlf→\r\n,Mixed→majority_terminator, otherwise\n. It's stable under appending lines in its own style, so a revert that removes{line}{nl}still finds what the forward pass wrote;fn restore_rendering(original, rendered): the toml_edit re-expansion, moved frompython_lock, with one documented mixed-file rule (per replaced fragment, as Fix Poetry/PDM lock splice drift (#694, #695) #703 does).Whether a writer refuses a mixed file stays a per-format decision, but it reads the same classifier.
Checklist
line_endings::terminator), deletingcommon::detect_eol, bothnewline_ofcopies and the inline copies. Pick the line terminator for spliced lines through one line_endings::terminator #815preserve_line_endingsand hosted cargo'scrlf_to_lfintoutils::line_endings(restore_rendering/LineEndings::of), adopting the per-fragment rule from Fix Poetry/PDM lock splice drift (#694, #695) #703 for toml_edit output. After Fix Poetry/PDM lock splice drift (#694, #695) #703.block_eol) on both forward and revert (fixes Yarn classic hosted and vendored rewrites convert LF lines of a mixed CRLF/LF yarn.lock to CRLF, so rollback is not byte-exact #467). After E08 (yarn grammars).formats/pnpm/lines.rs(review 4.7 G). It's tracked under that refactor, not here.Dependencies
Child 1 can start now. Child 2 is blocked by PR #703. Child 3 should follow PR #657 and E08.