| #!/bin/bash |
| # |
| # git-archive-signer |
| # ------------------ |
| # Use this script to create a tarball signature for a tag and store |
| # it as part of the repo (using git notes, as supported by cgit). |
| |
| # Don't change this if you want this to actually work |
| NOTEREF="refs/notes/signatures/tar" |
| NOTEREF_MINISIG="refs/notes/minisig/tar" |
| |
| # Pass the tag as the only parameter, otherwise we grab the latest |
| # annotated tag we find. You may also pass "list" to list all tags that |
| # already carry corresponding signature notes. |
| if [[ $1 == "list" ]]; then |
| git notes --ref ${NOTEREF} list | cut -d' ' -f2 | xargs git describe |
| exit 0 |
| fi |
| |
| TAG=$1 |
| |
| # Set this to your gitolite.kernel.org remote |
| # We'll also use git config --get archive-signer.remote if we find it |
| REMOTE="$(git config --get archive-signer.remote)" |
| if [[ -z ${REMOTE} ]]; then |
| REMOTE="origin" |
| fi |
| |
| # Change this if your gpg2 is elsewhere |
| GPGBIN="/usr/bin/gpg2" |
| # Change this if your minisign is elsewhere |
| MINISIGNBIN="/usr/bin/minisign" |
| |
| # If you want to use a specific key (or subkey) instead of the default, |
| # then edit and uncomment this line. If you have multiple valid signing |
| # subkeys, then add the exact subkey ID and add a "!" at the end. |
| # We'll also use git config archive-signer.usekey value if we find it |
| #USEKEY="Ox12345678DEADBEEF" |
| USEKEY="$(git config --get archive-signer.usekey)" |
| |
| # We use TARNAME when making a git archive --prefix, e.g. $TARNAME-1.2.3/ |
| # Set it here if guessing basename is wrong. |
| # We'll also use git config archive-signer.tarname value if we find it |
| TARNAME="$(git config --get archive-signer.tarname)" |
| if [[ -z ${TARNAME} ]]; then |
| TARNAME="$(basename $(pwd))" |
| fi |
| |
| # You shouldn't need to change anything below |
| |
| if [[ -z ${TAG} ]]; then |
| # Assume you want the latest tag |
| TAG="$(git describe --abbrev=0)" |
| if [[ -z ${TAG} ]]; then |
| echo "Could not figure out which tag you want" |
| exit 1 |
| fi |
| fi |
| |
| # The archive prefix will be created as $TARNAME-$TAG/ (sans leading v) |
| # Change it here if it doesn't correspond to your needs |
| # We'll add the trailing / where it is needed, so don't add it here |
| PREFIX="${TARNAME}-${TAG#v}" |
| |
| # Do we already have a signature note for this tag? |
| # Start by fetching the origin notes |
| echo "Updating notes from remote" |
| git fetch ${REMOTE} "refs/notes/*:refs/notes/*" |
| if git notes --ref=${NOTEREF} list ${TAG} >/dev/null 2>&1; then |
| echo "Signature note for ${TAG} already exists!" |
| echo "To make a new one, delete it first:" |
| echo " git notes --ref=${NOTEREF} remove ${TAG}" |
| exit 1 |
| fi |
| |
| echo -n "Generate signature note for ${PREFIX}.tar? [Y/n] " |
| read YN |
| |
| [[ -z ${YN} ]] && YN=y |
| [[ ${YN} != "y" ]] && exit 1 |
| |
| # We add the exact archive line to sig comments, |
| # so put it together here |
| GIT_ARCHIVE_CMD="git archive --format tar --prefix=${PREFIX}/ ${TAG}" |
| # Record the version of git that created this archive |
| GIT_VERSION=$(git --version) |
| |
| if [[ ! -z ${USEKEY} ]]; then |
| GPGBIN="${GPGBIN} -u ${USEKEY}" |
| fi |
| |
| # We put the tarball into a temp file, in case we need to minisign it, too |
| TMP_ARCHIVE=$(mktemp) |
| echo -n "Running ${GIT_ARCHIVE_CMD}..." |
| ${GIT_ARCHIVE_CMD} > ${TMP_ARCHIVE} |
| echo "done" |
| git notes --ref=${NOTEREF} add -C "$( |
| cat ${TMP_ARCHIVE} | ${GPGBIN} -a -b -o - \ |
| --comment "This signature is for the .tar version of the archive" \ |
| --comment "${GIT_ARCHIVE_CMD}" \ |
| --comment "${GIT_VERSION}" | |
| git hash-object -w --stdin)" "${TAG}" |
| |
| if [[ $? != 0 ]]; then |
| echo "git notes exited with error" |
| rm -f ${TMP_ARCHIVE} |
| exit 1 |
| fi |
| |
| echo |
| git --no-pager notes --ref=${NOTEREF} show ${TAG} |
| echo |
| |
| USE_MINISIGN="$(git config --get archive-signer.use-minisign)" |
| if [[ ${USE_MINISIGN} == "yes" ]]; then |
| if git notes --ref=${NOTEREF_MINISIG} list ${TAG} >/dev/null 2>&1; then |
| echo "Minisign note for ${TAG} already exists!" |
| echo "To make a new one, delete it first:" |
| echo " git notes --ref=${NOTEREF_MINISIG} remove ${TAG}" |
| exit 1 |
| fi |
| MINISIGN_CMD="${MINISIGNBIN}" |
| MINISIGN_COMMENT="This minisign signature is for the .tar version of the archive" |
| MINISIGN_TRUSTED="$(date -u), ${GIT_VERSION}, using: ${GIT_ARCHIVE_CMD}" |
| # If minisign-keyfile is set, we'll use that key instead of the default |
| MINISIGN_KEY="$(git config --get archive-signer.minisign-key)" |
| if [[ ! -z ${MINISIGN_KEY} ]]; then |
| MINISIGN_CMD="${MINISIGN_CMD} -s $(eval echo ${MINISIGN_KEY})" |
| fi |
| # If you don't want to type in the minisign passphrase, you can |
| # store it gpg-encrypted and set archive.signer.minisign-gpg-passphrase to |
| # point at the file containing the encrypted passphrase. |
| # To generate, use: |
| # echo passphrase | gpg -r YOURKEYID -e > minisign-passphrase.gpg |
| MINISIGN_PASSPHRASE="$(git config --get archive-signer.minisign-gpg-passphrase)" |
| MINISIGN_OUT=$(mktemp) |
| echo "Generating minisign signature" |
| if [[ -z ${MINISIGN_PASSPHRASE} ]]; then |
| ${MINISIGN_CMD} -S \ |
| -c "${MINISIGN_COMMENT}" -t "${MINISIGN_TRUSTED}" \ |
| -x ${MINISIGN_OUT} -m ${TMP_ARCHIVE} |
| else |
| echo "Using the gpg-encrypted passphrase from ${MINISIGN_PASSPHRASE}" |
| ${GPGBIN} -q -d $(eval echo ${MINISIGN_PASSPHRASE}) \ |
| | ${MINISIGN_CMD} -S \ |
| -c "${MINISIGN_COMMENT}" -t "${MINISIGN_TRUSTED}" \ |
| -x ${MINISIGN_OUT} -m ${TMP_ARCHIVE} |
| fi |
| if [[ ! -s ${MINISIGN_OUT} ]]; then |
| # Assume minisign process went wrong |
| echo "Minisign signature is missing, aborting!" |
| rm -f ${TMP_ARCHIVE} |
| exit 1 |
| fi |
| git notes --ref=${NOTEREF_MINISIG} add \ |
| -C "$(cat ${MINISIGN_OUT} | git hash-object -w --stdin)" "${TAG}" |
| |
| if [[ $? != 0 ]]; then |
| echo "git notes exited with error" |
| rm -f ${TMP_ARCHIVE} ${MINISIGN_OUT} |
| exit 1 |
| fi |
| |
| echo "-----" |
| git --no-pager notes --ref=${NOTEREF_MINISIG} show ${TAG} |
| echo "-----" |
| echo |
| |
| rm -f ${MINISIGN_OUT} |
| fi |
| |
| rm -f ${TMP_ARCHIVE} |
| |
| echo -n "Push to ${REMOTE}? [Y/n] " |
| read YN |
| echo |
| |
| [[ -z ${YN} ]] && YN=y |
| if [[ ${YN} != "y" ]]; then |
| echo "Remember to push it using:" |
| echo " git push ${REMOTE} refs/notes/*" |
| exit 0 |
| fi |
| |
| echo "Pushing notes to ${REMOTE}..." |
| git push ${REMOTE} refs/notes/* |