diff options
Diffstat (limited to 'upstream_workon/upstream_workon.bash')
-rwxr-xr-x | upstream_workon/upstream_workon.bash | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/upstream_workon/upstream_workon.bash b/upstream_workon/upstream_workon.bash new file mode 100755 index 00000000..f066bbe3 --- /dev/null +++ b/upstream_workon/upstream_workon.bash @@ -0,0 +1,273 @@ +#!/bin/bash -eu +# +# Copyright 2021 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. + +USAGE=\ +'Usage: upstream-workon [-h] + init <PACKAGE> <DEV_WORK_DIR> + link <PACKAGE> <DEV_WORK_DIR> + build <PACKAGE> + install <PACKAGE> + clean <PACKAGE> + help' + +set +e +read -r -d '' HELP <<'EOF' +Usage: upstream-workon [-h] + init <PACKAGE> <DEV_WORK_DIR> + link <PACKAGE> <DEV_WORK_DIR> + build <PACKAGE> + install <PACKAGE> + clean <PACKAGE> + help + +Flags: + -h --help Print this help message + +Commands: + init Initialize in a developer workdir using a new tree + link Link an existing developer source dir to portage workdir + build Build the package using ebuild ... compile + install Install the package using ebuild ... install + clean Clean up your work without deleting the developer workdir + help Print this help message + +Examples: + + # Start work + mkdir "$HOME/llvm" + upstream-workon init sys-devel/llvm "$HOME/llvm" + + # Link your existing work + upstream-workon link sys-devel/llvm "$HOME/llvm" + + # Compile your work + upstream-workon build sys-devel/llvm + + # Install your changes to the chroot + upstream-workon install sys-devel/llvm + + # Clean up + upstream-workon clean sys-devel/llvm + +EOF +set -e + +incorrect_number_of_arguments() { + echo 'ERROR: Please use correct command syntax' >&2 + echo "${USAGE}" >&2 + exit 1 +} + +print_experimental_warning() { + echo >&2 + echo '!!! WARNING: This tool is EXPERIMENTAL--please do not rely on the API.' >&2 + echo '!!! WARNING: Please recommend new features for Version 2, but this' >&2 + echo '!!! WARNING: implementation will not be actively developed and' >&2 + echo '!!! WARNING: exists only to receive feedback and minor fixes.' >&2 +} + +# ------------------------------------------------------------------------------ +# Actual logic +# ------------------------------------------------------------------------------ + +# We probably can just pass through "USE", but I think this gives a bit more +# flexibility in the future. +USE_FLAGS="${USE:-}" + +if [[ -n "${USE_FLAGS}" ]]; then + echo 'USE flags set to:' + echo " ${USE_FLAGS}" +fi + +init() { + local package="$1" + local desired_src_loc="$2" + local ebuild_loc + ebuild_loc="$(resolve_ebuild_for "${package}")" + + local ebuild_name + ebuild_name="$(basename "${ebuild_loc}" | sed 's/\.ebuild$//g')" + local package_name + # SC2001 complains about not using variable replace syntax. + # However, variable remove syntax is not sufficiently expansive + # to do this replacement easily. + # shellcheck disable=2001 + package_name="$(sed 's/-r[0-9]\+$//g' <<< "${ebuild_name}")" + local ebuild_category + ebuild_category="$(basename "$(dirname "$(dirname "${ebuild_loc}")")")" + local portage_dir='/var/tmp/portage' + + local work_dir="${portage_dir}/${ebuild_category}/${ebuild_name}/work/${package_name}" + + ebuild "${ebuild_loc}" clean + USE="${USE_FLAGS}" ebuild "${ebuild_loc}" unpack + + # May need to init git if it doesn't already exist. + # Probably could just use git -C instead of the pushd/popd. + pushd "${work_dir}" >& /dev/null + if [[ ! -d '.git' ]]; then + git init + git add . + git commit -m 'Initial commit' + fi + popd >& /dev/null + + USE="${USE_FLAGS}" ebuild "${ebuild_loc}" configure + + cp -r -p "${work_dir}/." "${desired_src_loc}" + local backup_dir="${work_dir}.bk" + mv "${work_dir}" "${backup_dir}" + ln -s "$(realpath "${desired_src_loc}")" "${work_dir}" + + pushd "${desired_src_loc}" >& /dev/null + + git add . + git commit -m 'Ebuild configure commit' + popd >& /dev/null + + echo + echo '----------------------------------------' + echo 'Successfully created local mirror!' + echo "Developer work directory set up at: ${desired_src_loc}" + echo 'To build the package, run:' + echo " upstream-workon build ${package}" + echo 'To install the package, run:' + echo " sudo upstream-workon install ${package}" + echo "To clean up (without deleting ${desired_src_loc}), run:" + echo " upstream-workon clean ${package}" + echo "WARNING: Moving original workdir to ${backup_dir}, consider deleting" >&2 +} + +clean() { + local package="$1" + echo 'WARNING: You may need to run this with sudo' >&2 + local ebuild_loc + ebuild_loc="$(resolve_ebuild_for "${package}")" + + ebuild "${ebuild_loc}" clean + + echo '----------------------------------------' + echo "Successfully cleaned up ${package}!" +} + + +compile() { + local package="$1" + local ebuild_loc + ebuild_loc="$(resolve_ebuild_for "${package}")" + + USE="${USE_FLAGS}" ebuild "${ebuild_loc}" compile + + echo '----------------------------------------' + echo "Successfully compiled ${package}!" +} + + +install_src() { + local package="$1" + echo 'WARNING: You may need to run this with sudo' >&2 + local ebuild_loc + ebuild_loc="$(resolve_ebuild_for "${package}")" + + USE="${USE_FLAGS}" ebuild "${ebuild_loc}" install + + echo '----------------------------------------' + echo "Successfully installed ${package}!" +} + +link_src() { + local package="$1" + local desired_src_loc="$2" + local ebuild_loc + ebuild_loc="$(resolve_ebuild_for "${package}")" + + local ebuild_name + ebuild_name="$(basename "${ebuild_loc}" | sed 's/\.ebuild$//g')" + local package_name + # shellcheck disable=2001 + package_name="$(sed 's/-r[0-9]\+$//g' <<< "${ebuild_name}")" + local ebuild_category + ebuild_category="$(basename "$(dirname "$(dirname "${ebuild_loc}")")")" + local portage_dir='/var/tmp/portage' + + local work_dir="${portage_dir}/${ebuild_category}/${ebuild_name}/work/${package_name}" + + local backup_dir="${work_dir}.bk" + + # Because of some annoying permissions issues, we have to configure directly in + # /var/tmp/portage/... + # We then copy over those changes into our local source directory. + # To make sure the proper deletions get done, we delete everything except + # your local git directory. + + ebuild "${ebuild_loc}" clean + USE="${USE_FLAGS}" ebuild "${ebuild_loc}" configure + # TODO(ajordanr): This is a rough edge, and I don't want users to delete their + # home directory without knowing what they are doing. So we're copying + # everything instead. + # TODO(ajordanr): This will ignore git submodules, which I don't want. + mv "${desired_src_loc}" "${desired_src_loc}.bk" + mkdir "${desired_src_loc}" + cp -rP "${desired_src_loc}.bk/.git" "${desired_src_loc}/.git" + rsync -a --exclude=".git" "${work_dir}"/* "${desired_src_loc}" + rsync -a --exclude=".git" "${work_dir}"/.[^.]* "${desired_src_loc}" + mv "${work_dir}" "${backup_dir}" + ln -s "$(realpath "${desired_src_loc}")" "${work_dir}" + + echo '----------------------------------------' + echo 'Successfully linked to local mirror!' + echo "Developer work directory linked to: ${desired_src_loc}" + echo "WARNING: Moving original workdir to ${backup_dir}, consider deleting" >&2 + echo "WARNING: Moving original dev dir to ${desired_src_loc}.bk, consider deleting" >&2 +} + +resolve_ebuild_for() { + equery w "$1" +} + +CMD="${1:-}" + +case "${CMD}" in + -h|--help|help) + shift + echo "${HELP}" + print_experimental_warning + exit 1 + ;; + init) + shift + [[ -z "${1:-}" || -z "${2:-}" ]] && incorrect_number_of_arguments + print_experimental_warning + init "$1" "$2" + ;; + link) + shift + [[ -z "${1:-}" || -z "${2:-}" ]] && incorrect_number_of_arguments + print_experimental_warning + link_src "$1" "$2" + ;; + build) + shift + [[ -z "${1:-}" ]] && incorrect_number_of_arguments + print_experimental_warning + compile "$1" + ;; + clean) + shift + [[ -z "${1:-}" ]] && incorrect_number_of_arguments + print_experimental_warning + clean "$1" + ;; + install) + shift + [[ -z "${1:-}" ]] && incorrect_number_of_arguments + print_experimental_warning + install_src "$1" + ;; + *) + incorrect_number_of_arguments + ;; +esac |