#!/bin/bash

# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Simple wrapper script to build the chromeos-chrome package incrementally.

. /usr/lib/crosutils/common.sh || (echo "Unable to load common.sh")

get_default_board

DEFINE_string board "${DEFAULT_BOARD}" \
    "Board for which to build the package."
DEFINE_boolean runhooks "${FLAGS_FALSE}" \
    "Re-run hooks contained in the DEPS file - i.e., regenerate Makefiles."
DEFINE_boolean build_tests "${FLAGS_FALSE}" \
    "Build test targets."

# Parse command line.
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"

if [ $# -ne 0 ]; then
  echo "Usage: ${0} [OPTIONS]"
  exit 1
fi

if [ -z "${FLAGS_board}" ]; then
  die "You must specify --board="
fi

if [ -n "${FLAGS_board}" ]; then
  BOARD_DIR=/build/"${FLAGS_board}"
  EBUILDCMD=ebuild-"${FLAGS_board}"
  EMERGECMD=emerge-"${FLAGS_board}"
  EQUERYCMD=equery-"${FLAGS_board}"
  BOARD_STR="${FLAGS_board}"
  BOARD_KEYWORD="$(portageq-${FLAGS_board} envvar ARCH)"
fi

chrome_workon="chromeos-base/chromeos-chrome"
chrome="chromeos-chrome"
unstable_suffix="9999"
workon_name="${chrome}-${unstable_suffix}"
cache_dir="/build/${BOARD_STR}/tmp/cros_chrome_make"
useflags_file="${cache_dir}/PREV_USEFLAGS"
src_hash_file="${cache_dir}/PREV_SRC_HASH"
gerrit_chrome_root="/home/$(whoami)/trunk/chromium"
gerrit_chrome_src="${gerrit_chrome_root}/src"
pkgfile=
workpath=

cros_workon_list() {
  # Get list of packages being cros-worked on.
  cros_workon --board="${FLAGS_board}" list
}

get_upstream_base_hash() {
  # Get the upstream change that the local changes in the repo is based on.
  # This gets updated on a rebase (happens during repo sync).
  echo $(cd ${gerrit_chrome_src}; git merge-base m/master HEAD)
}

get_prev_useflags() {
  # Get the user-specified USE flags from the last run
  if [ -e ${useflags_file} ]; then
    cat ${useflags_file}
  fi
}

get_prev_src_hash() {
  # Get the upstream hash that the local changes were based on the last time
  # hooks were run.
  if [ -e ${src_hash_file} ]; then
    cat ${src_hash_file}
  fi
}

was_last_run_gerrit_src() {
  # Checks the symlink to CHROME_ROOT in the working dir to see if the last run
  # was done with CHROME_ORIGIN=GERRIT_SOURCE
  if [ -e "${workpath}/work/${workon_name}" ] && \
     [ "$(readlink -f "${workpath}/work/${workon_name}")" = \
       "${gerrit_chrome_root}" ]; then
    return 0   # True
  else
    return 1   # False
  fi
}

was_last_run_local_src() {
  # Checks the symlink to CHROME_ROOT in the working dir to see if the last run
  # was done with CHROME_ORIGIN=LOCAL_SOURCE
  if [ ! -e "${workpath}/work/${workon_name}" ] || \
     was_last_run_gerrit_src; then
    return 1   # False
  else
    return 0   # True
  fi
}

decide_use_flags() {
  # Do not set 'runhooks' useflag here because we don't want to consider it
  # when comparing use flags between runs.
  if [ "${FLAGS_build_tests}" = "${FLAGS_FALSE}" ]; then
    echo "${USE} -build_tests"
  else
    echo "${USE} build_tests"
  fi
}

decide_auto_runhooks_local_src() {
  # Decide whether to run 'gclient runhooks' for LOCAL_SOURCE.
  # We rerun hooks when user-specified useflags change.
  local _runhooks=0   # True
  if [ -e "${workpath}/.prepared" ] && was_last_run_local_src && \
     [ "$(get_prev_useflags)" = "$(decide_use_flags)" ]; then
    _runhooks=1   # False
  fi

  return ${_runhooks}
}

decide_auto_runhooks_gerrit_src() {
  # Decide whether to run 'chrome_set_ver --runhooks' for GERRIT_SOURCE.
  # We rerun hooks when either:
  # 1. user-specified useflags change. OR
  # 2. chromium/src is rebased - i.e. after the user runs 'repo sync'.
  local _runhooks=0   # True
  if [ -e "${workpath}/.prepared" ] && was_last_run_gerrit_src && \
     [ "$(get_prev_useflags)" = "$(decide_use_flags)" ] && \
     [ "$(get_prev_src_hash)" = "$(get_upstream_base_hash)" ]; then
       _runhooks=1   # False
  fi

  return ${_runhooks}
}

# Make temporary cache directory
#
# We keep three pieces of information in the temp directory:
# 1. The useflags set by the user on the last run.
# 2. In the case of CHROME_ORIGIN==GERRIT_SOURCE, The git hash of the upstream
#    change chromium/src is based on.  A change in the git hash alerts us to a
#    'repo sync' that was run, in which case we need to re-run hooks.
if [ ! -e ${cache_dir} ]; then
  mkdir ${cache_dir}
fi

# Find the ebuild file.
if ! pkgfile=$(ACCEPT_KEYWORDS="~${BOARD_KEYWORD}" "${EQUERYCMD}" which \
   "${workon_name}" 2> /dev/null); then
  die "error looking up ${chrome}"
fi

# Find the portage work directory for this package.
workpath="/build/${BOARD_STR}/tmp/portage/$( \
          echo "${pkgfile}" | \
            awk -F '/' '{ print $(NF-2) "/" $(NF-1) }')-${unstable_suffix}"

use="$(decide_use_flags)"

local_source=
if [ "$(cros_workon_list | grep ${chrome_workon})" != "${chrome_workon}" ]; then
  auto_runhooks=decide_auto_runhooks_local_src
  local_source="CHROME_ORIGIN=LOCAL_SOURCE"
else
  auto_runhooks=decide_auto_runhooks_gerrit_src
fi

runhooks="-runhooks"
if [ "${FLAGS_runhooks}" = "${FLAGS_TRUE}" ] || ${auto_runhooks}; then
  runhooks="runhooks"
fi

# TODO(rcui): crosbug.com/20435.  Investigate not running 'clean' and just
# re-running the compile stage when the Chrome build switches to Ninja inside
# the chroot.
eval "USE='${use} -verbose ${runhooks}'" CCACHE_SIZE=2G \
     FEATURES="ccache" ${local_source} \
     "${EBUILDCMD}" "${pkgfile}" clean compile

# If we didn't get to run hooks, don't update our cache.
if [ -e "${workpath}/.prepared" ]; then
  echo "${use}" > ${useflags_file}
  if [ -z "${local_source}" ]; then
    echo "$(get_upstream_base_hash)" > ${src_hash_file}
  fi
fi
