fix(install): validate --commit SHA and fail hard on fetch/checkout errors (#87268)
Three problems with install.sh --commit:
1. No validation: non-hex or too-short arguments passed through to git,
producing misleading errors.
2. Fetch failure swallowed by || true: abbreviated SHAs are refused by
GitHub's server ("couldn't find remote ref"), but the error was
silently ignored.
3. Checkout failure not checked: git checkout --detach with a missing
object produces a misleading "does not take a path argument" error
and the install continues unpinned, exiting 0.
Fix:
- Validate --commit is a 7-40 hex string up front
- Remove || true from fetch; fail with actionable message directing
users to full 40-char SHAs
- Check git checkout --detach result and fail hard on error
Fixes #87268
This commit is contained in:
@@ -1384,6 +1384,13 @@ EOF
|
||||
cd "$INSTALL_DIR"
|
||||
|
||||
if [ -n "$INSTALL_COMMIT" ]; then
|
||||
# Validate the commit argument: must look like a hex SHA (full 40-char
|
||||
# or abbreviated 7-39 char). Reject anything else early so the user
|
||||
# gets a clear error instead of a misleading git message (#87268).
|
||||
if ! printf '%s' "$INSTALL_COMMIT" | grep -qE '^[0-9a-fA-F]{7,40}$'; then
|
||||
log_error "--commit expects a hex SHA (7-40 chars), got: $INSTALL_COMMIT"
|
||||
return 1
|
||||
fi
|
||||
# A commit pin must never move an existing install BACKWARDS. The
|
||||
# bootstrap installer bakes its build-time commit into the binary
|
||||
# (BUILD_PIN_COMMIT) and passes it as --commit on every install-mode
|
||||
@@ -1393,21 +1400,32 @@ EOF
|
||||
# current venv. Only pin when the target is not already an ancestor of
|
||||
# HEAD; a fresh clone has no such ancestry and pins normally.
|
||||
if ! git cat-file -e "$INSTALL_COMMIT^{commit}" 2>/dev/null; then
|
||||
git fetch origin "$INSTALL_COMMIT" || true
|
||||
if ! git fetch origin "$INSTALL_COMMIT"; then
|
||||
log_error "Could not fetch commit $INSTALL_COMMIT from origin."
|
||||
log_error "Abbreviated SHAs are not supported — use the full 40-char hash."
|
||||
log_error "Find it with: git ls-remote origin | grep <short-sha>"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if git rev-parse --verify --quiet HEAD >/dev/null 2>&1 \
|
||||
&& git merge-base --is-ancestor "$INSTALL_COMMIT" HEAD 2>/dev/null \
|
||||
&& [ "$(git rev-parse "$INSTALL_COMMIT^{commit}" 2>/dev/null)" != "$(git rev-parse HEAD)" ]; then
|
||||
if [ "$FORCE_COMMIT" = true ]; then
|
||||
log_warn "--force-commit: rolling this install back to $INSTALL_COMMIT."
|
||||
git checkout --detach "$INSTALL_COMMIT"
|
||||
if ! git checkout --detach "$INSTALL_COMMIT"; then
|
||||
log_error "Failed to detach at $INSTALL_COMMIT"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_warn "Ignoring --commit $INSTALL_COMMIT: the checkout is already newer."
|
||||
log_warn "Pinning to it would roll this install back. Pass --force-commit to override."
|
||||
fi
|
||||
else
|
||||
log_info "Pinning checkout to commit $INSTALL_COMMIT..."
|
||||
git checkout --detach "$INSTALL_COMMIT"
|
||||
if ! git checkout --detach "$INSTALL_COMMIT"; then
|
||||
log_error "Failed to detach at $INSTALL_COMMIT"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user