Handle no-TTY gracefully in post-checkout hook#14
Merged
Conversation
GUI Git clients (Fork, Sourcetree, Xcode, VS Code, etc.) run post-checkout hooks without a TTY, so sudo cannot prompt for a password when install.sh needs to write to /usr/local/bin. Previously this caused the hook to fail with a cryptic sudo error. The fix is surgical: only the Luca self-update path (curl | bash install.sh) requires sudo and therefore needs a TTY. The luca install step that syncs tools from the Lucafile does not require elevated privileges and should still run regardless. Behaviour with no TTY: - Luca absent: log a clear warning and exit 0 (nothing more can be done without the binary) - Version mismatch: log a warning naming the installed and required versions, then fall through to `luca install` so Lucafile tools are still synced using whatever version is currently installed Behaviour with a TTY: unchanged. The check uses `[ ! -t 0 ]` (stdin is not a terminal) rather than stdout, since sudo reads the password from stdin. Tests updated to reflect that bats runs without a TTY (so the no-TTY path is the natural path exercised). The old "luca absent: curl called to install" test was asserting behaviour that cannot run in a headless test environment; it is replaced by assertions on the no-TTY skip output. A new test confirms that a version mismatch with no TTY still proceeds to `luca install`. README diagrams for the post-checkout hook (flowchart and sequence diagram) updated to show the TTY decision point and its two outcomes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
GUI Git clients (Fork, Sourcetree, Xcode, VS Code, GitKraken, etc.) run post-checkout hooks without a TTY. When switching to a branch that requires a different Luca version, the hook calls
install.shwhich invokessudoto write the Luca binary to/usr/local/bin. Without a TTY, sudo cannot prompt for a password and exits with an error:Root Cause
install.sh:sudo_if_install_dir_not_writeablecallssudo sh -c "..."whenever/usr/local/binis not writable by the current user. GUI clients close stdin and stdout from the terminal, so sudo has no way to prompt for a password.Fix
The fix is surgical — only the Luca self-update path (the
curl | bash install.shinvocation) requires sudo and therefore a TTY. The subsequentluca installstep that syncs tools from the Lucafile does not need elevated privileges and should still run regardless of whether a TTY is present.Before entering the self-update block, the hook now checks
[ ! -t 0 ](stdin is not a terminal):luca installluca installluca installThe version-mismatch + no-TTY case deliberately falls through to
luca installso that Lucafile tools are still synchronised using the currently installed Luca binary — the wrong version is used, but that is better than silently doing nothing. The warning message makes the situation clear and directs the user to re-run setup from a terminal.[ -t 0 ](stdin) is used rather than[ -t 1 ](stdout) because it is stdin that sudo needs to read the password from.Behaviour Examples
No TTY, luca absent:
Hook exits 0. No confusing sudo error. Nothing further can be done without the binary.
No TTY, version mismatch (e.g. installed 0.20.0, branch requires 0.17.0):
Hook exits 0, tools are still synced.
Changes
post-checkout— TTY check wrapping the self-update block; no-TTY paths log actionable warnings and either exit early (no binary) or fall through toluca install(version mismatch).tests/post_checkout.bats— updated one existing test that was asserting behaviour impossible in a headless (no-TTY) test environment; added two new tests covering the no-TTY paths explicitly.README.md— post-checkout flowchart and sequence diagram updated to show the TTY decision point and its two outcomes.Testing
All 14 bats tests pass. The bats runner itself has no TTY, which means the no-TTY paths are exercised naturally by the test suite without any special scaffolding.
The TTY=true installation path (where
install.shis actually fetched and run) is not directly testable in bats since the runner has no TTY, but that code path is unchanged from the pre-fix behaviour.