blob: e5c286b27740e148ee8d3757399d6001fd4353f7 [file]
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (c) Jarkko Sakkinen 2025
set -e
SOURCE="git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git"
TEMPLATE_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/linux-pr"
usage() {
echo "Usage: $0 [-n|--dry-run] [-C <linux kernel tree>] [--postfix <postfix>] [--data-dir <data dir>] <template name> <version>"
}
git_kernel() {
git -C "$kernel_tree" "$@"
}
render_template() {
jq \
--rawfile template "$template" \
--arg tag "$tag" \
--arg version "$version" \
--arg pull_request "$pull_request" \
--arg sender "$sender" \
--arg sender_email "$sender_email" \
--arg timestamp "$timestamp" \
-rn '
$template
| gsub("{{sender}}"; $sender)
| gsub("{{sender_email}}"; $sender_email)
| gsub("{{timestamp}}"; $timestamp)
| gsub("{{tag}}"; $tag)
| gsub("{{version}}"; $version)
| sub("{{pull_request}}"; $pull_request)
'
}
kernel_tree=.
dry_run=
postfix=
data_dir="$TEMPLATE_DIR"
while [[ $# -gt 0 ]]; do
case "$1" in
-n|--dry-run)
dry_run=1
shift
;;
-C)
if [[ $# -lt 2 ]]; then
usage >&2
exit 1
fi
kernel_tree="$2"
shift 2
;;
--postfix)
if [[ $# -lt 2 || -z "$2" ]]; then
usage >&2
exit 1
fi
postfix="$2"
shift 2
;;
--data-dir)
if [[ $# -lt 2 || -z "$2" ]]; then
usage >&2
exit 1
fi
data_dir="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
--)
shift
break
;;
-*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
*)
break
;;
esac
done
if [[ -z "$kernel_tree" || $# -ne 2 ]]; then
usage >&2
exit 1
fi
if ! git -C "$kernel_tree" rev-parse --show-toplevel >/dev/null 2>&1; then
echo "\"$kernel_tree\" is not a git repository" >&2
exit 1
fi
template_name="$1"
version="$2"
if [[ -z "$template_name" || "$template_name" == */* ]]; then
echo "Invalid template name: \"$template_name\"" >&2
exit 1
fi
template="$data_dir/$template_name.mbox.in"
if [[ ! -f "$template" || ! -r "$template" ]]; then
echo "Template \"$template_name\" not found or unreadable: $template" >&2
exit 1
fi
tag="${template_name}-${version}"
git_tag="${tag}${postfix:+-$postfix}"
tag_ref="refs/tags/$git_tag"
if git_kernel show-ref --verify --quiet "$tag_ref"; then
echo "\"$git_tag\" pre-exists"
exit 1
fi
if git_kernel ls-remote --exit-code --refs --tags origin "$tag_ref" >/dev/null 2>&1; then
echo "\"origin/$git_tag\" pre-exists"
exit 1
fi
sender_email="$(git_kernel config user.email)"
sender="$(git_kernel config user.name) <$sender_email>"
timestamp=$(date +"%a %b %e %H:%M:%S %Y")
pull_request='{{pull_request}}'
subject=$(render_template | jq -Rrs '
split("\n\n")[0]
| split("\n")[]
| select(startswith("Subject: "))
| ltrimstr("Subject: ")
')
if [[ -z "$subject" ]] || grep -Eq '\{\{[^}]+\}\}' <<< "$subject"; then
echo "\"$template\" has a missing or unresolved subject" >&2
exit 1
fi
if [[ -n "$dry_run" ]]; then
request_ref="HEAD:$tag_ref"
printf "Dry run: using '%s' as request-pull end ref\n" "$request_ref" >&2
pull_request=$(git_kernel request-pull mainline/master "$SOURCE" "$request_ref" 2>/dev/null) || true
if [[ -z "$pull_request" ]]; then
git_kernel request-pull mainline/master "$SOURCE" "$request_ref" >/dev/null
fi
else
request_ref="$git_tag"
git_kernel tag -s --edit -m "$subject" -m "Signed-off-by: $sender" "$git_tag"
git_kernel push origin "$git_tag"
printf "Waiting for '%s'" "$git_tag" >&2
while ! git ls-remote --exit-code --refs --tags "$SOURCE" "$tag_ref" >/dev/null 2>&1; do
printf "." >&2
sleep 1
done
printf " found\n" >&2
pull_request=$(git_kernel request-pull mainline/master "$SOURCE" "$request_ref")
fi
output="git-pull-${tag}.mbox"
tmp_output="$(mktemp "${output}.XXXXXX")"
trap 'rm -f "$tmp_output"' EXIT
render_template > "$tmp_output"
if grep -Eq '\{\{[^}]+\}\}' "$tmp_output"; then
echo "\"$template\" contains unresolved placeholders" >&2
exit 1
fi
mv "$tmp_output" "$output"
trap - EXIT