#!/bin/sh
# script/lint-fix: run the linter's autofixer. Rewrites files in place
# for every finding the enabled linters know how to fix; findings
# without an autofix are reported but left alone.
#
# THIS IS A DEVELOPER CONVENIENCE AND NEVER A GATE. Nothing in
# script/check, script/precommit or script/cibuild calls it, and no gate
# reads its exit status. The gate is script/lint, which builds
# Dockerfile.lint; run that afterwards to find out whether the tree is
# actually clean.
#
# Unlike script/lint this cannot be a build step: a build step writes
# into an image, and fixes have to land in the worktree. So it runs the
# same pinned image as a container with the tree bind-mounted, which
# means it needs a LOCAL docker daemon -- a remote daemon has no access
# to these files, and this script will appear to do nothing there. The
# image reference is parsed out of Dockerfile.lint's FROM line, so the
# autofixer is always the same version as the linter that gates; fixes
# written by a different version are not necessarily fixes for the
# version that decides.
set -eu

ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
DOCKERFILE="$ROOT/Dockerfile.lint"

# The image reference from Dockerfile.lint, tag and digest included.
lint_image() {
    awk '$1 == "FROM" { print $2; exit }' "$DOCKERFILE"
}

main() {
    cd "$ROOT"

    image="$(lint_image)"
    if [ -z "$image" ]; then
        echo "lint-fix: no FROM line found in $DOCKERFILE" >&2
        exit 1
    fi

    # Run as the invoking user so the rewritten files stay owned by
    # them. HOME is set because the Go and golangci-lint caches default
    # under it and that user has no home inside the container; those
    # caches are per-container and discarded with it.
    docker run --rm \
        --user "$(id -u):$(id -g)" \
        --env HOME=/tmp \
        --env GOFLAGS=-buildvcs=false \
        --volume "$ROOT:/src" \
        --workdir /src \
        "$image" \
        golangci-lint run --config .golangci.yml --fix "$@" ./...
}

main "$@"
