#!/usr/bin/env bash

# This script determines the set of tests to run for a set of files that have
# changed, and which changed files aren't covered by any tests
#
# This explicitly excludes BUILD and .bzl files because we don't have tests for
# them, and they're generally covered by running a build anyway

set -euo pipefail 

upstream="origin/master"
files_changed=$(mktemp)
tests=$(mktemp)
untested_files=$(mktemp)
test_targets=""

function cleanup {
  rm -f "$files_changed" "$tests" "$untested_files"
  [[ -n "$test_targets" ]] && rm "$test_targets"
}
trap cleanup EXIT

# Get list of files changed when compared to upstream.
# Filter out paths that end with /BUILD (build files in packages)
# Filter out paths that begin with build/BUILD (external build files)
# Filter out paths that end with .bzl
# Filter out paths that begin with experimental/
# Filter out paths that end with OWNERS or README.md
git diff --diff-filter ACMRTXB --name-only "$upstream" | grep -v '/BUILD$' | grep -v '^experimental/' | grep -v '^build/BUILD' | grep -v '\.bzl$' | grep -v 'README\.md$' | grep -v 'OWNERS$' > "$files_changed"

changed_file_count=$(cat "$files_changed" | wc --lines)
echo "$changed_file_count files changed compared to upstream:"

for f in $(cat "$files_changed") ; do
  test_targets=$(mktemp)
  bazel query "kind(test, rdeps(..., $f))" > "$test_targets" 2>/dev/null || true
  num_tests=$(cat "$test_targets" | wc --lines)
  if [[ "$num_tests" -gt 0 ]] ; then
    cat "$test_targets" >> "$tests"
  else
    echo "$f" >> "$untested_files"
  fi

  rm "$test_targets"
  test_targets=""

  # Progress meter
  echo -n .
done
echo

echo "Tests to run"
if [[ -n "$1" ]] ; then
  sort "$tests" | uniq > "$1"
  echo "Written to $1"
  shift
else
  sort "$tests" | uniq
fi

echo
echo "Untested files"
if [[ -n "$1" ]] ; then
  sort "$untested_files" | uniq > "$1"
  echo "Written to $1"
  shift
else
  sort "$untested_files" | uniq
fi
