diff options
author | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2021-12-30 00:52:26 +0100 |
---|---|---|
committer | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2021-12-30 02:33:47 +0100 |
commit | fdac4cf8364c02760312a8c9650de24dba0007e5 (patch) | |
tree | 0dd858e0a277c6c9b84bca06e6edf806eb0a73f3 | |
parent | 82bfee48f074c496347e77e277d63cd1c7c1155a (diff) | |
download | vendor_replicant-release-scripts-fdac4cf8364c02760312a8c9650de24dba0007e5.tar.gz vendor_replicant-release-scripts-fdac4cf8364c02760312a8c9650de24dba0007e5.tar.bz2 vendor_replicant-release-scripts-fdac4cf8364c02760312a8c9650de24dba0007e5.zip |
Add script to copy the release patches to a remote build machine
This script makes a patch out of the latest commit from the following
repositories:
- ../vendor_replicant-release-scripts
- ../vendor_replicant
- ../manifest
it then apply them inside the respective directories inside the
replicant directory on another machine, with SSH and Rsync.
When doing a release we typically need to change the Replicant
version, and so that requires to add 1 patch to each of the
repositories mentioned above.
However in some cases, the Replicant directory is on another
computer. This is for instance the case for people working on their
laptop and building Replicant on another machine.
The release process already takes care of that situation but it
required to manually apply patches on the remote builder before
tagging the source code.
And the Replicant 6.0 0004 RC6 release failed because some patches
were missing in the released (and signed) source code. So it's better
to automate things to avoid forgetting patches for the next releases.
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
-rwxr-xr-x | builder-patches.sh | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/builder-patches.sh b/builder-patches.sh new file mode 100755 index 0000000..4934a56 --- /dev/null +++ b/builder-patches.sh @@ -0,0 +1,262 @@ +#!/usr/bin/env sh +# Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# +# 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 <https://www.gnu.org/licenses/>. + +# 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 \ +" + +local_tmpdir="$(mktemp -d)" + +usage() +{ + echo "Usage:" + echo "$0 <machine> <replicant_dir> apply" \ + " # Apply patches to the remote git repositories" + echo "$0 <machine> <replicant_dir> remove" \ + "# Remove the last commit from the remote git repositories" + echo "$0 <machine> <replicant_dir> reset" \ + " # run git reset --hard on the remote git repositories" + echo "$0 <machine> <replicant_dir> 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 + patch="$(git -C ${repository} format-patch -1)" + destdir="${local_tmpdir}/$(basename ${repository})" + + mkdir -p "${destdir}/" + mv -f "${repository}/${patch}" "${destdir}/" + + append "patches" "$(basename ${repository})/${patch}" + append "repositories_dirs" "$(basename ${repository})" + 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 |