diff --git a/bin/quickgogen b/bin/quickgogen new file mode 120000 index 0000000..8165259 --- /dev/null +++ b/bin/quickgogen @@ -0,0 +1 @@ +../scripts/dev/quickgogen.sh \ No newline at end of file diff --git a/lib/git.sh b/lib/git.sh index 6de326c..18e0ec1 100644 --- a/lib/git.sh +++ b/lib/git.sh @@ -11,6 +11,22 @@ function get_current_branch() { echo "${ref#refs/heads/}" } +# Gets the main branch or dies. +function get_main_branch_or_die() { + # From https://stackoverflow.com/questions/28666357/git-how-to-get-default-branch#comment92366240_50056710 + local main_branch + main_branch="$(git remote show origin | grep "HEAD branch" | sed 's/.*: //')" + [[ -n "${main_branch}" ]] || die "Failed to get main branch" + echo "${main_branch}" +} + +# Gets the diffbase off of the remote's main branch or dies. +function get_diffbase_or_die() { + diffbase="$(git merge-base HEAD "origin/${main_branch}")" + [[ $? -eq 0 ]] || die "Failed to determine diffbase" + echo "${diffbase}" +} + function get_remote() { local remote remote="$(git config --get remote.origin.url)" @@ -67,3 +83,13 @@ function branch_exists() { local branch="$1" git show-ref --verify --quiet "refs/heads/$branch" } + +# TODO(do-not-merge): How return multi-line output properly? +# Requires $gitroot. +# Returns the list of .go file paths in $gitroot (with $gitroot prefix) +# that have a comment saying they are generated files. +function quick_get_generated_files { + echo "$(git -C "$gitroot" \ + grep -l '^// Code generated by .* DO NOT EDIT\.' -- '*.go' | \ + sed -e "s@^@${gitroot}/@")" +} \ No newline at end of file diff --git a/scripts/dev/quickgogen.sh b/scripts/dev/quickgogen.sh new file mode 100755 index 0000000..99a9914 --- /dev/null +++ b/scripts/dev/quickgogen.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +# Usage: Runs gogen for all Go files that have changed between the current code and master. + +SCRIPT="$(python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "${BASH_SOURCE[0]}")" +source "$(dirname "$SCRIPT")/../../lib/common.sh" +source "$(dirname "$SCRIPT")/../../lib/git.sh" + +gitroot="$(git rev-parse --show-toplevel)" +[[ $? -eq 0 ]] || die "Current directory is not a git repository." + +if [[ -f "${gitroot}/go.mod" ]]; then + export GO111MODULE=on +fi + +# Various code generation helpers are expected to be in the PATH when called by go generate. +export PATH="$PATH:${gitroot}/tools/generate-helpers" + +main_branch="$(get_main_branch_or_die)" +diffbase="$(get_diffbase_or_die)" + +generated_files="$(git -C "$gitroot" grep -l '^// Code generated by .* DO NOT EDIT\.' -- '*.go' | sed -e "s@^@${gitroot}/@")" + +IFS=$'\n' read -d '' -r -a changed_files < <( + { + git diff "$diffbase" --name-status . | + sed -n -E -e "s@^[AM][[:space:]]+|^R[^[:space:]]*[[:space:]]+[^[:space:]]+[[:space:]]+@${gitroot}/@p" ; + echo "$generated_files" ; echo "$generated_files" +} | sort | uniq -u) || true + +function private_gogen() { + local status=0 + local changed_files=("$@") + local gofiles + + IFS=$'\n' read -d '' -r -a gofiles < <( + printf '%s\n' "${changed_files[@]}" | + grep '\.go$' + ) + [[ "${#gofiles[@]}" == 0 ]] && return 0 + + IFS=$'\n' read -d '' -r -a godirs < <( + for f in "${gofiles[@]}"; do dirname "$f"; done | + sort | uniq) + + einfo "Running go generate..." + for dir in "${godirs[@]}"; do + einfo "...Generating for ${dir}" + ( cd "$dir" && go generate "./" ) && (( status == 0 )) + status=$? + done + + return "${status}" +} + +[[ "${#changed_files[@]}" -eq 0 ]] && { ewarn "No relevant changes found in current directory."; exit 0; } +status=0 + +private_gogen "${changed_files[@]}" && (( status == 0 )) +status=$? + +[[ "${status}" -eq 0 ]] && exit 0 +efatal "An error occurred while generating files" +exit 1 diff --git a/scripts/dev/quickstyle.sh b/scripts/dev/quickstyle.sh index 0b1daf1..b10b657 100755 --- a/scripts/dev/quickstyle.sh +++ b/scripts/dev/quickstyle.sh @@ -8,6 +8,7 @@ SCRIPT="$(python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "${BASH_SOURCE[0]}")" source "$(dirname "$SCRIPT")/../../lib/common.sh" source "$(dirname "$SCRIPT")/../../setup/packages.sh" +source "$(dirname "$SCRIPT")/../../lib/git.sh" check_dependencies @@ -222,12 +223,8 @@ if [[ -f "${gitroot}/go.mod" ]]; then export GO111MODULE=on fi -# https://stackoverflow.com/a/44750379 -main_branch="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" -[[ -n "${main_branch}" ]] || die "Failed to get main branch" - -diffbase="$(git merge-base HEAD "origin/${main_branch}")" -[[ $? -eq 0 ]] || die "Failed to determine diffbase" +main_branch="$(get_main_branch_or_die)" +diffbase="$(get_diffbase_or_die)" generated_files="$(git -C "$gitroot" grep -l '^// Code generated by .* DO NOT EDIT\.' -- '*.go' | sed -e "s@^@${gitroot}/@")"