#!/bin/bash

# Development script: bisect a git repository to find the first broken commit
# since the last known good version.

# If any of the pipe segments fail, treat that as a fail.

set -o pipefail

if test $Argc -lt 4
{
  echo "usage: bisectinate ARCH PACKAGE REPO[@BAD] GOOD [TEST...]" >&2
  echo >&2
  echo "Bisect PACKAGE for ARCH, from START to BAD within REPO" >&2
  exit 1
}

# Parse command line options

setvar ARCH = "$1"
setvar PKG = "$2"
setvar REPO = "${3/@*/}"
setvar BRANCH = "${3/*@/}"
test $BRANCH == $3 && setvar BRANCH = 'master'
setvar START = "$4"
shift 4
setvar TEST = "$1"

setvar TOP = "$(pwd)"
test -z $SRCDIR && setvar SRCDIR = ""$TOP/packages""
test -z $BUILD && setvar BUILD = ""$TOP/build""

if test ! -d "$REPO/.git"
{
  echo "No git repo at $REPO"
  exit 1
}

test -z $TEST && setvar TEST = 'true'

# For kernel and busybox bisects, only redo part of the build

if test $PKG == linux && test -e "$BUILD/root-filesystem-$ARCH".tar.bz2
{
  setvar ZAPJUST = 'linux-kernel'
} elif test $PKG == busybox &&
     test -e "$BUILD/simple-cross-compiler-$ARCH.tar.bz2"
{
  setvar ZAPJUST = 'root-filesystem'
} else {
  setvar ZAPJUST = ''
}

# Initialize bisection repository

rm -rf "$BUILD/packages/alt-$PKG" "$SRCDIR/alt-$PKG-0.tar.bz2" &&
mkdir -p "$BUILD"/{logs,packages} &&
cd "$BUILD/packages" &&
git clone $REPO "alt-$PKG" &&
cd "alt-$PKG" &&
git bisect start &&
git bisect good $START || exit 1

setvar RESULT = ""bad $BRANCH""

# Loop through bisection results

while true
{
  # Bisect repository to prepare next version to build.  Exit if done.

  cd "$BUILD/packages/alt-$PKG" &&
  git clean -fdx &&
  git checkout -f || exit 1

  setvar RESULT = "$(git bisect $RESULT)"
  echo $RESULT
  test ! $(echo "$RESULT" | head -n 1 | grep "^Bisecting:") && exit

  # Update log

  git show > "$BUILD/logs/bisectinate-${ARCH}.txt"
  git bisect log > "$BUILD/logs/bisectinate-${ARCH}.log"
  # The "cat" bypasses git's stupid overengineered built-in call to less.
  git log HEAD -1 | cat
  echo "Testing..."

  cd $TOP || exit 1

  # Figure out how much ./build.sh needs to rebuild

  test ! -z $ZAPJUST &&
    rm -rf "$BUILD/${ZAPJUST}-$ARCH"{,.tar.bz2} ||
    rm -rf' "$BUILD"/*-"$ARCH"{,.tar.bz2}

  # Try the build

  EXTRACT_ALL=1'' ALLOW_PATCH_FAILURE=1'" USE_ALT=$PKG" \
    ./build.sh $ARCH 2>&1 | tee -a "$BUILD"/logs/bisectinate-"$ARCH".txt

  # Did it work?

  setvar RESULT = 'bad'
  if test -e "$BUILD"/system-image-"$ARCH".tar.bz2
  {
    set -o pipefail"
    ARCH=$ARCH" more/timeout.sh 60 $TEST 2>&1 | \
      tee -a "$BUILD/logs/bisectinate-$ARCH".txt
    test $? -eq 0 && setvar RESULT = 'good'
  }

  # Keep the last "good" and "bad" logs, separately.

  mv "$BUILD"/logs/bisectinate{,-$RESULT}-"$ARCH".txt
}