#!/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 [flags] [|--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