#!/usr/bin/env bash
# usage: maint-bench.sh <bare-repo> [workdir]
# BIN=<maint-bench binary> compares another revision's build; the source repo is never modified.
set -euo pipefail

src=$(realpath "$1")
work=${2:-$(mktemp -d)}
bin=${BIN:-}
if [ -z "$bin" ]; then
  root=$(cd "$(dirname "$0")" && git rev-parse --show-toplevel)
  cargo build -q --profile profiling --manifest-path "$root/Cargo.toml" -p knot-bench --bin maint-bench
  bin=$root/target/profiling/maint-bench
fi
repo=$work/repo
mkdir -p "$work"

cow_copy() {
  rm -rf "$2"
  if [ "$(uname)" = Darwin ]; then /bin/cp -cR "$1" "$2"; else cp -a --reflink=auto "$1" "$2"; fi
}

run() {
  local scenario=$1 err out mem
  shift
  err=$(mktemp)
  if [ "$(uname)" = Darwin ]; then
    out=$(/usr/bin/time -l "$bin" "$@" 2>"$err") || out="failed=$? $(grep -v '^ ' "$err" | tail -1)"
    mem="footprint=$(awk '/peak memory footprint/ {print $1}' "$err") maxrss=$(awk '/maximum resident/ {print $1}' "$err")"
  else
    out=$(/usr/bin/env time -f 'maxrss_kb=%M' "$bin" "$@" 2>"$err") || out="failed=$? $(tail -2 "$err" | head -1)"
    mem=$(tail -1 "$err")
  fi
  rm -f "$err"
  echo "scenario=$scenario $out $mem"
}

add_commit() {
  local blob tree commit
  blob=$(echo "bench $RANDOM $RANDOM $(date +%s)" | git --git-dir="$repo" hash-object -w --stdin)
  tree=$(printf '100644 blob %s\tbench\n' "$blob" | git --git-dir="$repo" mktree)
  commit=$(GIT_AUTHOR_NAME=bench GIT_AUTHOR_EMAIL=bench@localhost \
    GIT_COMMITTER_NAME=bench GIT_COMMITTER_EMAIL=bench@localhost \
    git --git-dir="$repo" commit-tree "$tree" -p HEAD -m bench)
  git --git-dir="$repo" update-ref HEAD "$commit"
}

cow_copy "$src" "$repo"
rm -rf "$repo"/objects/pack/*.bitmap "$repo"/objects/pack/multi-pack-index* "$repo"/objects/info/commit-graph*
run fresh maintain "$repo"
run settled maintain "$repo"

run walk clone "$repo" --walk
for threads in 1 4 8; do
  run bitmap clone "$repo" --threads "$threads"
done
for behind in 10 1000; do
  run walk fetch "$repo" --behind "$behind"
  run bitmap fetch "$repo" --behind "$behind" --bitmap
done

add_commit
run loose maintain "$repo"

add_commit
git --git-dir="$repo" repack -q
run second-pack maintain "$repo"
run second-pack-bitmap clone "$repo"
