Skip to content

q2 add: keep unknown record keys, refuse newer records, pin line endings - #1183

Merged
cscheid merged 3 commits into
mainfrom
feature/bd-yjg91sls-quarto-source-record-contract
Nov 11, 2026
Merged

cscheid merged 3 commits into
mainfrom
feature/bd-yjg91sls-quarto-source-record-contract

Conversation

@cscheid

@cscheid cscheid commented Nov 11, 2026

Copy link
Copy Markdown
Member

Makes .quarto-source.yml safe to share with other tools. Quarto Wizard's development version now writes this record too. Strand: bd-yjg91sls. Plan: claude-notes/plans/2026-11-11-quarto-source-record-contract.md.

Fixes #1175. Fixes #1176. Part of #1177 (the line-ending rule). The spec and JSON Schema (#1177) and track/commit (#1178) are still under discussion in the plan doc, and aren't in this PR.

Changes

Unknown keys are kept (#1175). SourceRecord gains a flattened extra: serde_yaml::Mapping, which keeps the keys in file order. record::inspect replaces installed_state and also returns the parsed record. write_record is now per extension: q2 sets the keys it owns (version, source, kind, ref, files) and copies every other key from the record being replaced. Nothing is carried over from an unreadable record or from one with a newer schema version.

Newer schema versions (#1176). parse_record reads version before parsing the rest. Above RECORD_VERSION, it returns EditKind::NewerRecord(v). That goes through the existing local-changes refusal, so replacing the record needs --force, and the error adds an "Upgrade q2" hint. Checking the version first matters: a v2 record that doesn't fit v1's shapes is still reported as newer, not as unreadable. A version that is 0, missing or not an integer reports as unreadable.

Line endings. On Windows, Git's core.autocrlf (on by default in Git for Windows) rewrites LF to CRLF on checkout. Every text file then stops matching its hash and looks locally edited.

  • Any run that writes an extension creates _extensions/.gitattributes with * -text when the file is missing. The file sits next to the extensions, not inside one, so it is never hashed and doesn't clash with a .gitattributes an extension ships. An existing file is never edited. [No Change] and --dry-run don't write it; the dry run prints "would also create". --json gains gitattributes_written.
  • The rule is -text, not eol=lf: eol=lf converts on commit, which would break extensions that ship CRLF files. The plan doc has the reasoning and the precedents (cargo vendor, go.sum).
  • A file that differs from its hash only by CRLF↔LF (either direction) is reported as line endings changed, with a hint that names autocrlf and the .gitattributes fix. It still needs --force, so other tools reading the record keep the same exact hash rule.

The user guide (docs/guides/authoring/extensions.qmd) has the new behavior.

Testing

  • New unit tests in record.rs: extra keys round-trip in order and don't count as edits; a newer version is reported even when the rest doesn't parse; version 0, missing or not an integer is unreadable; CRLF and LF conversions in both directions; a real edit made with CRLF still counts as modified.
  • New end-to-end tests in tests/integration/add.rs follow the repros in q2 add drops keys it doesn't know when it rewrites .quarto-source.yml #1175 and q2 add ignores the schema version of .quarto-source.yml and reads a newer record as version 1 #1176, plus .gitattributes creation (dry run, No Change, existing file, JSON) and the line-endings message.
  • Checked by hand in a real git repo: with a root * text=auto, git check-attr reports text: unset under _extensions/, and with core.autocrlf=true an LF file checks out as LF.
  • cargo xtask verify (Rust steps), then a full workspace run: 19,288 tests passed. One local failure isn't related to this PR: quarto-core knitr::capture_tests::capture_classifies_pieces gets rlang_error instead of simpleError from my local R 4.6 install. This PR doesn't touch quarto-core.
  • I couldn't cross-check the Windows build from macOS: ring's build script needs a Windows C toolchain. The change uses no platform-specific APIs, and paths in the new code go through Path::join.

🤖 Generated with Claude Code

t and others added 2 commits November 11, 2026 14:48
Triage of GH #1175-#1178 (Quarto Wizard now writes the same install
record), the CRLF/.gitattributes decision with the sources behind it,
and the open questions for the spec (#1177) and track/commit (#1178).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Makes `.quarto-source.yml` safe to share with other tools
(bd-yjg91sls):

- Keys q2 doesn't own survive a rewrite (#1175). `SourceRecord`
  gains a flattened `extra` mapping (file order kept); `record::inspect`
  returns the parsed prior record, and `write_record` carries its extra
  keys into the new record. Nothing is carried from an unreadable
  record or one with a newer schema version.
- A newer schema version is not read with v1 rules (#1176). The
  version is probed before the rest of the record is parsed, so a v2
  record that doesn't fit v1 shapes still reads as "newer", not
  "unreadable". It is reported as a local change (needs --force), with
  an "Upgrade q2" hint.
- Line endings. Any install that writes an extension creates
  `_extensions/.gitattributes` with `* -text` when it is missing (never
  edits an existing one; No Change and --dry-run write nothing), so
  git's core.autocrlf can't turn every file into a "local edit". A
  file that differs from its hash only by CRLF<->LF is reported as
  "line endings changed" with a hint naming the fix; it still needs
  --force. `--json` gains `gitattributes_written`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cscheid
cscheid merged commit 8e55bf4 into main Nov 11, 2026
17 checks passed
@cscheid
cscheid deleted the feature/bd-yjg91sls-quarto-source-record-contract branch November 11, 2026 23:14
cscheid pushed a commit that referenced this pull request Nov 11, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants