#!/usr/bin/env sh # Copyright (C) 2021 Denis 'GNUtoo' Carikli # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # During the release process, we need patches in the manifest, in # vendor/replicant and vendor/replicant-release-scripts to change the # Replicant revision. # When the person who does the release uses a separate computer to # build Replicant, in some cases, it makes sense to develop the patch # locally and push them to the remote. local_repositories="\ ../vendor_replicant-release-scripts \ ../vendor_replicant \ ../manifest \ " . $(dirname $0)/releasevars.sh local_tmpdir="$(mktemp -d)" usage() { echo "Usage:" echo "$0 apply" \ " # Apply patches to the remote git repositories" echo "$0 remove" \ "# Remove the last commit from the remote git repositories" echo "$0 reset" \ " # run git reset --hard on the remote git repositories" echo "$0 sync" \ " # run repo sync on the remote git repositories" echo "" echo "Remote repositories:" for repository in ${local_repositories} ; do echo "- $(basename ${repository} | sed 's#_#/#g')/" done exit 64 # EX_USAGE in sysexits.h } append_raw() { variable="$1" shift 1 values="$@" if [ -z "$(eval echo \$${variable})" ] ; then eval "${variable}=\"${values}\"" else eval "${variable}=\"\$${variable}${values}\"" fi } append() { variable="$1" shift 1 values="$@" if [ -z "$(eval echo \$${variable})" ] ; then eval "${variable}=\"${values}\"" else eval "${variable}=\"\$${variable} ${values}\"" fi } remote_commands="" queue_remote_commands() { commands="$@" if [ -z "${remote_commands}" ] ; then append_raw remote_commands "${commands}" else append_raw remote_commands ";${commands}" fi } apply_remote_commands() { machine="$1" ssh "${machine}" "${remote_commands}" remote_commands="" } patches_for_remote="" queue_patches_for_remote() { patches="$@" if [ -z "${patches_for_remote}" ] ; then append patches_for_remote "${patches}" else append patches_for_remote ";${patches}" fi } send_and_apply_patches_to_remote() { machine="$1" replicant_dir="$2" remote_tmpdir="$(mktemp -d --dry-run)" for patch in ${patches_for_remote} ; do append remote_tmpsubdirs "${remote_tmpdir}/$(dirname ${patch})" append local_patches_paths "${local_tmpdir}/./${patch}" queue_remote_commands \ "cd;cd ${replicant_dir}/$(dirname ${patch} | sed 's#_#/#g')" # TODO: check if the patch is already applied queue_remote_commands "git am ${remote_tmpdir}/${patch}" done queue_remove_remote_temporary_files "${remote_tmpdir}" rsync -Rrav ${local_patches_paths} "${machine}:${remote_tmpdir}/" apply_remote_commands "${machine}" patches_for_remote="" } remove_local_temporary_files() { tmpdirs="$@" for tmpdir in ${tmpdirs} ; do for patch in ${patches} ; do rm -f "${tmpdir}/${patch}" done for repository_dir in ${repositories_dirs} ; do rmdir "${tmpdir}/${repository_dir}/" done rmdir "${tmpdir}/" done } queue_remove_remote_temporary_files() { tmpdirs="$@" for tmpdir in ${tmpdirs} ; do for patch in ${patches} ; do queue_remote_commands "rm -f ${tmpdir}/${patch}" done for repository_dir in ${repositories_dirs} ; do queue_remote_commands \ "rmdir ${tmpdir}/${repository_dir}/" done queue_remote_commands "rmdir ${tmpdir}/" done } apply_patches_to_remote() { machine="$1" replicant_dir="$2" patches="" repositories_dirs="" for repository in ${local_repositories} ; do nr_patches=1 destdir="${local_tmpdir}/$(basename ${repository})" mkdir -p "${destdir}/" append "repositories_dirs" "$(basename ${repository})" if is_transition_release ; then if [ "${repository}" = "../vendor_replicant" ] ; then nr_patches=2 fi fi _patches="$(git -C ${repository} format-patch -${nr_patches})" for patch in ${_patches} ; do mv -f "${repository}/${patch}" "${destdir}/" append "patches" "$(basename ${repository})/${patch}" done done queue_patches_for_remote "${patches}" send_and_apply_patches_to_remote "${machine}" "${replicant_dir}" remove_local_temporary_files "${local_tmpdir}" } apply_git_reset_hard_to_remote() { machine="$1" replicant_dir="$2" patches="" repositories_dirs="" for repository in ${local_repositories} ; do remote_git_dir="$(echo $(basename ${repository}) \ | sed 's#_#/#g')" queue_remote_commands "cd;cd ${replicant_dir}" queue_remote_commands "git -C ${remote_git_dir} reset --hard" done apply_remote_commands "${machine}" } remove_top_patches_from_remote() { machine="$1" replicant_dir="$2" for repository in ${local_repositories} ; do remote_git_dir="$(echo $(basename ${repository}) \ | sed 's#_#/#g')" queue_remote_commands "cd;cd ${replicant_dir}" queue_remote_commands \ "GIT_EDITOR='echo noop > ' \ git -C ${remote_git_dir} rebase -i HEAD~1" done apply_remote_commands "${machine}" } repo_sync_remote_repositories() { machine="$1" replicant_dir="$2" for repository in ${local_repositories} ; do append \ "remote_repositories_paths" \ "$(echo $(basename ${repository})| sed 's#_#/#g')" done queue_remote_commands "cd;cd ${replicant_dir}" # When using repo sync, repo update itself automatically. But # the updated repo doesn't work anymore withTrisquel 9 python3 # version.To workaround that issue, Replicant released a # tarball (built with Guix) that includes a newer repo and all # its dependencies (including python). And to work properly we # need to source a script that setups the environment # variables to make that repo work. queue_remote_commands \ "[ -f /usr/local/bin/repo-env.sh ] && \ source /usr/local/bin/repo-env.sh" queue_remote_commands "repo sync ${remote_repositories_paths}" apply_remote_commands "${machine}" } if [ $# -ne 3 ] ; then usage elif [ "$3" = "apply" ] ; then apply_patches_to_remote "$1" "$2" elif [ "$3" = "remove" ] ; then remove_top_patches_from_remote "$1" "$2" elif [ "$3" = "reset" ] ; then apply_git_reset_hard_to_remote "$1" "$2" elif [ "$3" = "sync" ] ; then repo_sync_remote_repositories "$1" "$2" fi