#!/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.

# This script moves ebuilds between 'stable' and 'live' states.
# By default 'stable' ebuilds point at and build from source at the
# last known good commit. Moving an ebuild to 'live' (via cros_workon start)
# is intended to support development. The current source tip is fetched,
# source modified and built using the unstable 'live' (9999) ebuild.

. "$(dirname "$0")/common.sh" || exit 1

assert_not_root_user

# Script must be run inside the chroot

DEFINE_string board "${DEFAULT_BOARD}" \
  "The board to set package keywords for."
DEFINE_string brick "" \
  "The brick to set package keywords for."
DEFINE_boolean host "${FLAGS_FALSE}" \
  "Uses the host instead of board"
DEFINE_string remote "" \
  "For non-workon projects, the git remote to use."
DEFINE_string revision "" \
  "Use to override the manifest defined default revision used for a project"
DEFINE_string command "git status" \
  "The command to be run by forall."
DEFINE_boolean all "${FLAGS_FALSE}" \
  "Apply to all possible packages for the given command"
DEFINE_boolean workon_only "${FLAGS_FALSE}" \
  "Apply to packages that have a workon ebuild only"

FLAGS_HELP="usage: $0 <command> [flags] [<list of packages>|.|--all]
commands:
  start:     Moves an ebuild to live (intended to support development)
  stop:      Moves an ebuild to stable (use last known good)
  info:      Print package name, repo name, and source directory.
  list:      List of live ebuilds (workon ebuilds if --all)
  list-all:  List all of the live ebuilds for all setup boards
  iterate:   For each ebuild, cd to the source dir and run a command"
FLAGS "$@" || { [ "${FLAGS_help}" = "${FLAGS_TRUE}" ]  && exit 0; } || exit 1
eval set -- "${FLAGS_ARGV}"


# eat the workon command keywords: start, stop or list.
WORKON_CMD=$1
shift

# Board dir config

# --host takes precedence over --{brick,board}; --brick takes precedence over
# --board. This preserves prior behavior meant to accommodate default values.
if [[ "${FLAGS_host}" == ${FLAGS_TRUE} ]]; then
  if [[ -n "${FLAGS_board}" ]] || [[ -n "${FLAGS_brick}" ]]; then
    warn "--host was used, ignoring --brick and --board values"
    FLAGS_brick=""
    FLAGS_board=""
  fi
elif [[ -n "${FLAGS_brick}" ]]; then
  # Override board name with the brick's friendly name (backward compatibility).
  [[ -z "${FLAGS_board}" ]] || warn "--brick was used, ignoring --board value"
  FLAGS_board="$(cros_brick_utils --friendly-name "${FLAGS_brick}")"
  [[ -n "${FLAGS_board}" ]] || die_notrace
fi

if [ -z "${FLAGS_board}" ] && \
   [ "${FLAGS_host}" = ${FLAGS_FALSE} ] && \
   [ "${WORKON_CMD}" != "list-all" ]; then
  flags_help
  die "You must specify either --host, --board or --brick"
fi

if [ -n "${FLAGS_board}" ]; then
  BOARD_DIR=/build/"${FLAGS_board}" # --board specified
  EQUERYCMD=equery-"${FLAGS_board}"
  EBUILDCMD=ebuild-"${FLAGS_board}"
  PORTAGEQCMD=portageq-"${FLAGS_board}"
  BOARD_STR="${FLAGS_board}"
else
  BOARD_DIR="" # --host specified
  EQUERYCMD=equery
  EBUILDCMD=ebuild
  PORTAGEQCMD=portageq
  BOARD_STR="host"
fi

WORKON_DIR="${CHROOT_TRUNK_DIR}/.config/cros_workon"
CONFIG_DIR="${BOARD_DIR}/etc/portage"
KEYWORDS_DIR="${CONFIG_DIR}/package.keywords"
MASK_DIR="${CONFIG_DIR}/package.mask"
UNMASK_DIR="${CONFIG_DIR}/package.unmask"
WORKON_FILE="${WORKON_DIR}/${BOARD_STR}"
MASK_WORKON_FILE="${WORKON_FILE}.mask"
KEYWORDS_FILE="${KEYWORDS_DIR}/cros-workon"
MASK_FILE="${MASK_DIR}/cros-workon"
UNMASK_FILE="${UNMASK_DIR}/cros-workon"
CHROME_ATOM=chromeos-base/chromeos-chrome

mkdir -p "${WORKON_DIR}" || die "mkdir -p ${WORKON_DIR}"
touch "${WORKON_FILE}" "${MASK_WORKON_FILE}" || \
  die "touch ${WORKON_FILE} ${MASK_WORKON_FILE}"
cmds=(
  "mkdir -p '${KEYWORDS_DIR}' '${MASK_DIR}' '${UNMASK_DIR}'"

  # Clobber and re-create the WORKON_FILE symlinks every time. This
  # is a trivial operation and eliminates all kinds of corner cases
  # as well as any possible future renames of WORKON_FILE.
  # In particular, chroot is usually built as "amd64-host" but becomes
  # just "host" after installation. crosbug.com/23096
  "ln -sf '${WORKON_FILE}' '${KEYWORDS_FILE}'"
  "ln -sf '${MASK_WORKON_FILE}' '${MASK_FILE}'"
  "ln -sf '${WORKON_FILE}' '${UNMASK_FILE}'"
)
# If the board dir doesn't exist yet, we don't want to create it as
# that'll screw up ./setup_board later on.
if [[ -d ${BOARD_DIR:-/} ]] ; then
  sudo_multi "${cmds[@]}"
else
  die "${BOARD_STR} has not been setup yet"
fi


find_keyword_workon_ebuilds() {
  local keyword="${1}"
  local overlay

  # NOTE: overlay may be a symlink, and we have to use ${overlay}/
  for overlay in "${OVERLAYS[@]}"; do
    # Only look up ebuilds named 9999 to eliminate duplicates.
    # Packages inheriting from cros-workon or chromium-source are considered
    # workon-able.
    find "${overlay}"/*-* -maxdepth 2 -type f -name '*9999.ebuild' \
      -exec egrep -l '^inherit.*\<(cros-workon|chromium-source)\>' {} + \
      2>/dev/null | xargs egrep -l "KEYWORDS=\".*~([*]|${keyword})[ \"]"
  done
}

ebuild_to_package() {
  # This changes the absolute path to ebuilds into category/package.
  sed -e 's/.*\/\([^/]*\)\/\([^/]*\)\/.*\.ebuild/\1\/\2/'
}

show_project_ebuild_map() {
  local keyword="$1"
  local project_var

  # Column 1: Repo name
  # Column 2: Package name
  for EBUILD in $(find_keyword_workon_ebuilds ${keyword}); do
    (
      project_var=$(awk -- \
        '/CROS_WORKON_PROJECT=/,/CROS_WORKON_PROJECT=[^(]|\)/' "${EBUILD}")
      # Can only detect syntax errors in subshells; not in our own.
      if ( eval "${project_var}" ); then
        eval "${project_var}"
      else
        error "From $EBUILD, failed to eval:"
        error "$project_var"
        continue
      fi
      CP=$(echo "$EBUILD" | ebuild_to_package)
      projects=$(echo "${CROS_WORKON_PROJECT[@]}" | sed 's/ /,/g')
      echo "${projects:--}" "${CP}"
    )
  done
}

show_project_path_map() {
  # Column 1: Repo name
  # Column 2: Source directory
  repo list | awk -F ' : ' '{ print $2, $1 }'
}

show_workon_ebuilds() {
  local keyword="$1"
  find_keyword_workon_ebuilds "${keyword}" | ebuild_to_package | sort -u
}

# Prints only the atoms that have nothing but 9999 ebuilds across all overlays.
filter_workon_only() {
  local atoms="$1"
  local atom
  local num_ebuilds
  local overlay
  for atom in ${atoms}; do
    num_ebuilds=0
    for overlay in "${OVERLAYS[@]}"; do
      num_ebuilds=$(ls -1 "${overlay}"/${atom}/*.ebuild 2>/dev/null | wc -l)
      [[ "${num_ebuilds}" -gt 1 ]] && break
    done
    [[ "${num_ebuilds}" -le 1 ]] && echo ${atom}
  done
}

show_workon_info() {
   local atoms="$1"
   local keyword="$2"
   local sort="sort -k1b,1"
   # Column 1: Package name
   # Column 2: Repo name
   # Column 3: Source directory (if present locally)
   join \
     <(echo "${atoms}" | sed -e 's/ /\n/g' | ${sort}) \
     <(join -a 1 -e - -o 1.2,1.1,2.2 \
       <(show_project_ebuild_map "${keyword}" | ${sort}) \
       <(show_project_path_map | ${sort}) \
       | ${sort})
}

# Canonicalize package name to category/package.
canonicalize_name() {
  local pkgfile
  local pkgname

  if grep -qx "=$1-9999" "${WORKON_FILE}" ; then
    echo $1
    return 0
  fi

  if ! pkgfile=$(ACCEPT_KEYWORDS="~${ARCH}" ${EQUERYCMD} \
                 which --include-masked $1); then
    # Try to auto-complete it.
    local autopkgs=()
    for pkgname in $(show_workon_ebuilds); do
      if [[ ${pkgname} == *"$1"* ]]; then
        autopkgs+=( ${pkgname} )
      fi
    done
    case ${#autopkgs[@]} in
    0)
      warn "error looking up package $1" 1>&2
      return 1
      ;;
    1)
      # Do nothing -- fall through.
      ;;
    *)
      warn "Multiple autocompletes found: ${autopkgs[*]}"
      ;;
    esac
    pkgname=${autopkgs[0]}
    info "Autocompleted '$1' to: ${pkgname}"
    canonicalize_name "${pkgname}"
    return
  fi

  pkgname=$(echo "${pkgfile}" | awk -F '/' '{ print $(NF-2) "/" $(NF-1) }')

  # TODO(rcui): remove special casing of chromeos-chrome here when we make it
  # inherit from cros-workon / chromium-source class (chromium-os:19259).
  if [ "${pkgname}" != "${CHROME_ATOM}" ] && \
     ! grep -q "^inherit.*\<chromium-source\>" ${pkgfile} && \
     ! grep -q "cros-workon" ${pkgfile}; then
    warn "${pkgname} is not a cros-workon package" 1>&2
    return 1
  fi
  echo "${pkgname}"
  return 0
}

# Canonicalize a list of names.
canonicalize_names() {
  local atoms=$1
  local names=()
  local atom

  for atom in ${atoms}; do
    names+=( $(canonicalize_name "${atom}") ) || return 1
  done

  echo "${names[*]}"
}

# Locate the package name based on the current directory
locate_package() {
  local projectname=$(git config --get remote.cros.projectname ||
                      git config --get remote.cros-internal.projectname)
  if [ -z "${projectname}" ]; then
    die "No project in git config: Can not cros_workon . here"
  fi
  local reponame=$(show_project_ebuild_map |
                   grep "^${projectname} " | cut -d" " -f2)
  if [ -z "${reponame}" ]; then
    die "No matching package for ${projectname}: Can not cros_workon . here"
  else
    echo "${reponame}"
  fi
}

# Display ebuilds currently part of the live branch and open for development.
show_live_ebuilds() {
  sed -n 's/^=\(.*\)-9999$/\1/p' "${WORKON_FILE}"
}

# Display ebuilds currently part of the live branch and open for development
# for any board that currently has live ebuilds.
show_all_live_ebuilds() {
  local workon_file
  for workon_file in ${WORKON_DIR}/*; do
    if [[ -s ${workon_file} && ${workon_file} != *.mask ]] ; then
      echo -e "${V_BOLD_GREEN}$(basename ${workon_file}):${V_VIDOFF}"
      sed -n 's/^=\(.*\)-9999$/    \1/p' "${workon_file}"
      echo ""
    fi
  done
}

# This is called only for "cros-workon start". We dont handle the
# "stop" case since the local changes are ignored anyway since the
# 9999.ebuild is masked and we dont want to deal with what to do with
# the user's local changes.
regen_manifest_and_sync() {
  # Nothing to do unless you are working on the minilayout
  local manifest=${CHROOT_TRUNK_DIR}/.repo/manifest.xml
  if [ $(basename $(readlink -f ${manifest})) != "minilayout.xml" ]; then
    if [ -z "$(git config -f "${CHROOT_TRUNK_DIR}/.repo/manifests.git/config" \
               --get manifest.groups)" ]; then
      # Reaching here means that it's a full manifest w/out any groups set-
      # literal full manifest.
      return
    fi
  fi

  local need_repo_sync=
  local pkgname
  for pkgname in $(show_live_ebuilds); do
    local pkgpath="$(${EQUERYCMD} which "${pkgname}")"
    local pkginfo="$(${EBUILDCMD} "${pkgpath}" info |
                   grep -v 'pkg_info() is not defined')"
    if [ -z "${pkginfo}" ]; then
      continue  # No package information available
    fi

    eval "${pkginfo}"
    local trunkdir=$(readlink -m "${CHROOT_TRUNK_DIR}")

    local i
    for (( i=0; i < ${#CROS_WORKON_SRCDIR[@]}; ++i )); do
      [ -z "${CROS_WORKON_PROJECT[i]}" ] && continue
      need_repo_sync='yes'
      local srcdir=$(readlink -m "${CROS_WORKON_SRCDIR[i]}")
      local revision="${FLAGS_revision:+--revision=${FLAGS_revision}}"
      if [ -z "${FLAGS_remote}" ]; then
        loman add --workon "${CROS_WORKON_PROJECT[i]}" ${revision}
      else
        loman add --remote "${FLAGS_remote}" ${revision} \
          "${CROS_WORKON_PROJECT[i]}" "${srcdir#${trunkdir}/}"
      fi
    done
  done
  if [ -n "${need_repo_sync}" ]; then
    echo "Please run \"repo sync\" now."
  fi
}

# Move a stable ebuild to the live development catgeory.  The ebuild
# src_unpack step fetches the package source for local development.
ebuild_to_live() {
  local atoms=$1
  local atoms_success=()
  local atom

  for atom in ${atoms}; do
    if ! grep -qx "=${atom}-9999" "${WORKON_FILE}" ; then
      echo "=${atom}-9999" >> "${WORKON_FILE}" || \
        die "Could not update ${WORKON_FILE} with ${atom}"
      echo "<${atom}-9999" >> "${MASK_WORKON_FILE}" || \
        die "Could not update ${MASK_WORKON_FILE} with ${atom}"
      atoms_success+=( ${atom} )
    else
      warn "Already working on ${atom}"
    fi
  done
  if [ ${#atoms_success[@]} -gt 0 ]; then
    regen_manifest_and_sync
    info "Started working on '${atoms_success[*]}' for '${BOARD_STR}'"
  fi
}

# Move a live development ebuild back to stable.
ebuild_to_stable() {
  local atoms=$1
  local atoms_success=()
  local atom

  for atom in ${atoms}; do
    if grep -qx "=${atom}-9999" "${WORKON_FILE}" "${MASK_WORKON_FILE}" ; then
      sed -i -e "/^=${atom/\//\\/}-9999\$/d" "${WORKON_FILE}" || \
        die "Could not update ${WORKON_FILE} with ${atom}"
      sed -i -e "/^<${atom/\//\\/}-9999\$/d" "${MASK_WORKON_FILE}" || \
        die "Could not update ${WORKON_FILE} with ${atom}"
      atoms_success+=( ${atom} )
    else
      warn "Not working on ${atom}"
    fi
  done
  if [ ${#atoms_success[@]} -gt 0 ]; then
    info "Stopped working on '${atoms_success[*]}' for '${BOARD_STR}'"
  fi
}

# Run a command on all or a set of repos.
ebuild_iterate() {
  local atoms=$1
  local atom

  for atom in ${atoms}; do
    info "Running \"${FLAGS_command}\" on ${atom}"
    eval $(${EBUILDCMD} $(${EQUERYCMD} which ${atom}) info)
    for S in "${CROS_WORKON_SRCDIR[@]}"; do
      (cd "${S}" && bash -c "${FLAGS_command}")
    done
  done
}

unset use_list
[[ ${FLAGS_workon_only} = ${FLAGS_TRUE} ]] && use_list="--workon_only"
[[ ${FLAGS_all} = ${FLAGS_TRUE} ]] && use_list="--all"

# Only call portageq when absolutely required, and when we do, only run it
# once -- it's a slow beast and can easily take hundreds of milliseconds :(.
if [[ ${WORKON_CMD} != "list" || -n "${use_list}" ]] ; then
  ARCH=$(${PORTAGEQCMD} envvar ARCH)
  cmd=( cros_list_overlays )
  if [[ -n "${FLAGS_brick}" ]]; then
    cmd+=( --brick "${FLAGS_brick}" )
  else
    cmd+=( --all )
    if [[ -n "${FLAGS_board}" ]]; then
      cmd+=( --board "${FLAGS_board}" )
    fi
  fi
  OVERLAYS=( $("${cmd[@]}") )
fi

# --all and --workon_only make commands operate on different lists.
if [[ -n "${use_list}" ]]; then
  case ${WORKON_CMD} in
    start|info|list)
      ATOM_LIST=$(show_workon_ebuilds ${ARCH})
      if [[ "${use_list}" = "--workon_only" ]]; then
        ATOM_LIST=$(filter_workon_only "${ATOM_LIST}")
      fi;;
    stop|iterate)
      ATOM_LIST=$(show_live_ebuilds)
      if [[ "${use_list}" = "--workon_only" ]]; then
        ATOM_LIST=$(filter_workon_only "${ATOM_LIST}")
      fi;;
    *) die "${use_list} is invalid for the given command";;
  esac
else
  case ${WORKON_CMD} in
    start|stop|info|iterate)
      ATOM_LIST=$@
      if [ -z "${ATOM_LIST}" ]; then
        die "${WORKON_CMD}: No packages specified"
      fi
      if [ "${ATOM_LIST}" = "." ]; then
        ATOM_LIST=$(locate_package)
      fi
      if ! ATOM_LIST=$(canonicalize_names "${ATOM_LIST}"); then
        die "Error parsing package list"
      fi;;
    *) ;;
  esac
fi

case ${WORKON_CMD} in
  start) ebuild_to_live "${ATOM_LIST}" ;;
  stop) ebuild_to_stable "${ATOM_LIST}" ;;
  info) show_workon_info "${ATOM_LIST}" "${ARCH}" ;;
  list)
    if [[ -n "${use_list}" ]]; then
      for atom in ${ATOM_LIST}; do echo ${atom}; done
    else
      show_live_ebuilds
    fi;;
  list-all) show_all_live_ebuilds ;;
  iterate) ebuild_iterate "${ATOM_LIST}" ;;
  *)
    flags_help
    die "$(basename $0): command '${WORKON_CMD}' not recognized"
    ;;
esac
