Skip to content

Refuse partially staged files in sley ready --fix#16

Merged
cgraf78 merged 1 commit into
mainfrom
fix-ready-partial-staging
Jul 1, 2026
Merged

Refuse partially staged files in sley ready --fix#16
cgraf78 merged 1 commit into
mainfrom
fix-ready-partial-staging

Conversation

@cgraf78

@cgraf78 cgraf78 commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

Make the sley ready --fix git path refuse partially staged files, so
the commit gate shares one formatting-safety policy with the standalone
sley fix command.

sley ready --fix --commit is the real commit gate — the Git/Sapling
commit hook runs it on every commit-producing command. Its git --fix
path formatted each selected file in place with no guard against a
partially staged file (one with both staged and unstaged hunks).
Formatting rewrites the whole worktree file, folding the formatter's
output into the unstaged hunk — the exact corruption sley fix already
refuses via _sley_git_staged_partial_files. The two paths had
divergent, unsafe-vs-safe policy.

  • add the guard to the git --fix branch, gated on the staged/commit
    scope (_SLEY_SCOPE_CHANGE == staged) — the only scope with an index
    to corrupt; plain ready --fix and non-git repos are unaffected, matching
    sley fix
  • filter the selected files through _repo_existing_regular_files before
    the partial check, exactly as sley fix does, so symlinks and
    non-regular files (which the format loop skips anyway) can't trigger a
    spurious refusal
  • on a partial file, print the same "refusing files with staged and
    unstaged changes" message, drop the selected-files cache, and return 2,
    byte-for-byte matching sley fix
  • refusing partials first also makes the existing "formatter modified
    staged files" report accurate: every remaining file then has worktree
    content equal to its index, so the loop's worktree-hash comparison no
    longer mis-handles a file whose worktree differs from the index

Testing

  • new sley-behavior-test cases: ready --fix --commit refuses a single
    partial file (exit 2, formats nothing, worktree unchanged); refuses a
    mixed batch where any file is partial (refuse-all parity, clean file
    left unformatted); and still formats a fully-staged clean file (exit 1
    with the re-stage report) so the guard does not over-refuse
  • verified red-green: neutering the scope gate fails the refusal cases
    (formatter runs, worktree corrupted) while the clean-file case stays
    green
  • full suite green (./test/sley-test: ok); checkrun lint and
    shellcheck -x lib/sley/ready.sh clean

Summary

Make the `sley ready --fix` git path refuse partially staged files, so
the commit gate shares one formatting-safety policy with the standalone
`sley fix` command.

`sley ready --fix --commit` is the real commit gate — the Git/Sapling
commit hook runs it on every commit-producing command. Its git `--fix`
path formatted each selected file in place with no guard against a
partially staged file (one with both staged and unstaged hunks).
Formatting rewrites the whole worktree file, folding the formatter's
output into the unstaged hunk — the exact corruption `sley fix` already
refuses via `_sley_git_staged_partial_files`. The two paths had
divergent, unsafe-vs-safe policy.

- add the guard to the git `--fix` branch, gated on the staged/commit
  scope (`_SLEY_SCOPE_CHANGE == staged`) — the only scope with an index
  to corrupt; plain `ready --fix` and non-git repos are unaffected, matching
  `sley fix`
- filter the selected files through `_repo_existing_regular_files` before
  the partial check, exactly as `sley fix` does, so symlinks and
  non-regular files (which the format loop skips anyway) can't trigger a
  spurious refusal
- on a partial file, print the same "refusing files with staged and
  unstaged changes" message, drop the selected-files cache, and return 2,
  byte-for-byte matching `sley fix`
- refusing partials first also makes the existing "formatter modified
  staged files" report accurate: every remaining file then has worktree
  content equal to its index, so the loop's worktree-hash comparison no
  longer mis-handles a file whose worktree differs from the index

Testing

- new `sley-behavior-test` cases: `ready --fix --commit` refuses a single
  partial file (exit 2, formats nothing, worktree unchanged); refuses a
  mixed batch where any file is partial (refuse-all parity, clean file
  left unformatted); and still formats a fully-staged clean file (exit 1
  with the re-stage report) so the guard does not over-refuse
- verified red-green: neutering the scope gate fails the refusal cases
  (formatter runs, worktree corrupted) while the clean-file case stays
  green
- full suite green (`./test/sley-test`: ok); `checkrun lint` and
  `shellcheck -x lib/sley/ready.sh` clean
@cgraf78 cgraf78 merged commit af5eb69 into main Jul 1, 2026
11 of 12 checks passed
@cgraf78 cgraf78 deleted the fix-ready-partial-staging branch July 1, 2026 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant