blob: e9d02426be75dab227e9d604e489af2d3fe01d2d [file] [log] [blame]
#!/bin/bash
# Copyright (c) 2010 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.
# Load common constants. This should be the first executable line.
# The path to common.sh should be relative to your script's location.
. "$(dirname "$0")/common.sh"
# Load common functions for workon scripts.
. "$(dirname "$0")/lib/cros_workon_common.sh"
# Script must be run inside the chroot
restart_in_chroot_if_needed $*
get_default_board
DEFINE_string board "${DEFAULT_BOARD}" \
"The board to set package keywords for."
DEFINE_boolean host "${FLAGS_FALSE}" \
"Uses the host instead of board"
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"
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)
list: List of live ebuilds (workon ebuilds if --all)
iterate: For each ebuild, cd to the source dir and run a commond"
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
# eat the workon command keywords: start, stop or list.
WORKON_CMD=$1
shift
# board dir config
[ -n "${FLAGS_board}" ] && [ "${FLAGS_host}" = ${FLAGS_TRUE} ] && \
die "Flags --host and --board are mutually exclusive."
[ -z "${FLAGS_board}" ] && [ "${FLAGS_host}" = ${FLAGS_FALSE} ] && \
die "You must specify either --host or --board="
if [ -n "${FLAGS_board}" ]; then
BOARD_DIR=/build/"${FLAGS_board}" # --board specified
EQUERYCMD=equery-"${FLAGS_board}"
EBUILDCMD=ebuild-"${FLAGS_board}"
else
BOARD_DIR="" # --host specified
EQUERYCMD=equery
EBUILDCMD=ebuild
fi
KEYWORDS_DIR=${BOARD_DIR}/etc/portage/package.keywords
UNMASK_DIR=${BOARD_DIR}/etc/portage/package.unmask
KEYWORDS_FILE=${KEYWORDS_DIR}/cros-workon
UNMASK_FILE=${UNMASK_DIR}/cros-workon
sudo mkdir -p "${KEYWORDS_DIR}" "${UNMASK_DIR}" || \
die "mkdir -p ${KEYWORDS_DIR} ${UNMASK_DIR}"
sudo touch "${KEYWORDS_FILE}" "${UNMASK_FILE}" || \
die "touch ${KEYWORDS_FILE} ${UNMASK_FILE}"
# Canonicalize package name to category/package.
canonicalize_name () {
local pkgfile
local pkgname
if ! pkgfile=$(${EQUERYCMD} which $1); then
warn "error looking up package $1" 1>&2
return 1
fi
pkgname=$(\
echo "${pkgfile}" |awk -F '/' '{ print $(NF-2) "/" $(NF-1) }')
if ! 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=""
for atom in ${atoms}; do
local name=$(canonicalize_name "${atom}")
[ -n "${name}" ] || return 1
names+=" ${name}"
done
echo "${names}"
}
# Display ebuilds currently part of the live branch and open for development.
show_live_ebuilds () {
cat "${KEYWORDS_FILE}"
}
# 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
for atom in ${atoms}; do
if ! grep -qx "${atom}" "${KEYWORDS_FILE}" ; then
sudo bash -c "echo \"${atom}\" >> \"${KEYWORDS_FILE}\""
sudo bash -c "echo \"~${atom}-9999\" >> \"${UNMASK_FILE}\""
else
warn "Already working on ${atom}"
fi
done
}
# Move a live development ebuild back to stable.
ebuild_to_stable () {
local atoms=$1
for atom in ${atoms}; do
if grep -qx "${atom}" "${KEYWORDS_FILE}" ; then
# remove the keyword
sudo bash -c "grep -v '^${atom}\$' \"${KEYWORDS_FILE}\" > \
\"${KEYWORDS_FILE}+\""
sudo mv "${KEYWORDS_FILE}+" "${KEYWORDS_FILE}"
# remove the unmask
sudo bash -c "grep -v '^~${atom}-9999\$' \"${UNMASK_FILE}\" > \
\"${UNMASK_FILE}+\""
sudo mv "${UNMASK_FILE}+" "${UNMASK_FILE}"
else
warn "Not working on ${atom}"
fi
done
}
# Run a command on all or a set of repos.
ebuild_iterate() {
local atoms=$1
for atom in ${atoms}; do
info "Running \"${FLAGS_command}\" on ${atom}"
eval $(${EBUILDCMD} $(${EQUERYCMD} which ${atom}) info)
(cd "${CROS_WORKON_SRCDIR}" && bash -c "${FLAGS_command}")
done
}
# --all makes commands operate on different lists
if [ ${FLAGS_all} = "${FLAGS_TRUE}" ]; then
case ${WORKON_CMD} in
start) ATOM_LIST=$(show_workon_ebuilds);;
stop|iterate) ATOM_LIST=$(show_live_ebuilds);;
list) ;;
*) die "--all is invalid for the given command";;
esac
else # not selected --all
case ${WORKON_CMD} in
start|stop|iterate)
ATOM_LIST=$@
if [ -z "${ATOM_LIST}" ]; then
die "${WORKON_CMD}: No packages specified"
elif ! 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}" ;;
list) [ ${FLAGS_all} = "${FLAGS_FALSE}" ] && show_live_ebuilds || show_workon_ebuilds ;;
iterate)ebuild_iterate "${ATOM_LIST}" ;;
*) die "invalid cros_workon command" ;;
esac