| #!/bin/sh | |
| # Copyright (c) 2005 Linus Torvalds | |
| USAGE='[-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg>] <tagname> [<head>]' | |
| SUBDIRECTORY_OK='Yes' | |
| . git-sh-setup | |
| message_given= | |
| annotate= | |
| signed= | |
| force= | |
| message= | |
| username= | |
| list= | |
| verify= | |
| LINES=0 | |
| while test $# != 0 | |
| do | |
| case "$1" in | |
| -a) | |
| annotate=1 | |
| shift | |
| ;; | |
| -s) | |
| annotate=1 | |
| signed=1 | |
| shift | |
| ;; | |
| -f) | |
| force=1 | |
| shift | |
| ;; | |
| -n) | |
| case "$#,$2" in | |
| 1,* | *,-*) | |
| LINES=1 # no argument | |
| ;; | |
| *) shift | |
| LINES=$(expr "$1" : '\([0-9]*\)') | |
| [ -z "$LINES" ] && LINES=1 # 1 line is default when -n is used | |
| ;; | |
| esac | |
| shift | |
| ;; | |
| -l) | |
| list=1 | |
| shift | |
| case $# in | |
| 0) PATTERN= | |
| ;; | |
| *) | |
| PATTERN="$1" # select tags by shell pattern, not re | |
| shift | |
| ;; | |
| esac | |
| git rev-parse --symbolic --tags | sort | | |
| while read TAG | |
| do | |
| case "$TAG" in | |
| *$PATTERN*) ;; | |
| *) continue ;; | |
| esac | |
| [ "$LINES" -le 0 ] && { echo "$TAG"; continue ;} | |
| OBJTYPE=$(git cat-file -t "$TAG") | |
| case $OBJTYPE in | |
| tag) | |
| ANNOTATION=$(git cat-file tag "$TAG" | | |
| sed -e '1,/^$/d' | | |
| sed -n -e " | |
| /^-----BEGIN PGP SIGNATURE-----\$/q | |
| 2,\$s/^/ / | |
| p | |
| ${LINES}q | |
| ") | |
| printf "%-15s %s\n" "$TAG" "$ANNOTATION" | |
| ;; | |
| *) echo "$TAG" | |
| ;; | |
| esac | |
| done | |
| ;; | |
| -m) | |
| annotate=1 | |
| shift | |
| message="$1" | |
| if test "$#" = "0"; then | |
| die "error: option -m needs an argument" | |
| else | |
| message="$1" | |
| message_given=1 | |
| shift | |
| fi | |
| ;; | |
| -F) | |
| annotate=1 | |
| shift | |
| if test "$#" = "0"; then | |
| die "error: option -F needs an argument" | |
| else | |
| message="$(cat "$1")" | |
| message_given=1 | |
| shift | |
| fi | |
| ;; | |
| -u) | |
| annotate=1 | |
| signed=1 | |
| shift | |
| if test "$#" = "0"; then | |
| die "error: option -u needs an argument" | |
| else | |
| username="$1" | |
| shift | |
| fi | |
| ;; | |
| -d) | |
| shift | |
| had_error=0 | |
| for tag | |
| do | |
| cur=$(git show-ref --verify --hash -- "refs/tags/$tag") || { | |
| echo >&2 "Seriously, what tag are you talking about?" | |
| had_error=1 | |
| continue | |
| } | |
| git update-ref -m 'tag: delete' -d "refs/tags/$tag" "$cur" || { | |
| had_error=1 | |
| continue | |
| } | |
| echo "Deleted tag $tag." | |
| done | |
| exit $had_error | |
| ;; | |
| -v) | |
| shift | |
| tag_name="$1" | |
| tag=$(git show-ref --verify --hash -- "refs/tags/$tag_name") || | |
| die "Seriously, what tag are you talking about?" | |
| git-verify-tag -v "$tag" | |
| exit $? | |
| ;; | |
| -*) | |
| usage | |
| ;; | |
| *) | |
| break | |
| ;; | |
| esac | |
| done | |
| [ -n "$list" ] && exit 0 | |
| name="$1" | |
| [ "$name" ] || usage | |
| prev=0000000000000000000000000000000000000000 | |
| if git show-ref --verify --quiet -- "refs/tags/$name" | |
| then | |
| test -n "$force" || die "tag '$name' already exists" | |
| prev=`git rev-parse "refs/tags/$name"` | |
| fi | |
| shift | |
| git check-ref-format "tags/$name" || | |
| die "we do not like '$name' as a tag name." | |
| object=$(git rev-parse --verify --default HEAD "$@") || exit 1 | |
| type=$(git cat-file -t $object) || exit 1 | |
| tagger=$(git var GIT_COMMITTER_IDENT) || exit 1 | |
| test -n "$username" || | |
| username=$(git config user.signingkey) || | |
| username=$(expr "z$tagger" : 'z\(.*>\)') | |
| trap 'rm -f "$GIT_DIR"/TAG_TMP* "$GIT_DIR"/TAG_FINALMSG "$GIT_DIR"/TAG_EDITMSG' 0 | |
| if [ "$annotate" ]; then | |
| if [ -z "$message_given" ]; then | |
| ( echo "#" | |
| echo "# Write a tag message" | |
| echo "#" ) > "$GIT_DIR"/TAG_EDITMSG | |
| git_editor "$GIT_DIR"/TAG_EDITMSG || exit | |
| else | |
| printf '%s\n' "$message" >"$GIT_DIR"/TAG_EDITMSG | |
| fi | |
| grep -v '^#' <"$GIT_DIR"/TAG_EDITMSG | | |
| git stripspace >"$GIT_DIR"/TAG_FINALMSG | |
| [ -s "$GIT_DIR"/TAG_FINALMSG -o -n "$message_given" ] || { | |
| echo >&2 "No tag message?" | |
| exit 1 | |
| } | |
| ( printf 'object %s\ntype %s\ntag %s\ntagger %s\n\n' \ | |
| "$object" "$type" "$name" "$tagger"; | |
| cat "$GIT_DIR"/TAG_FINALMSG ) >"$GIT_DIR"/TAG_TMP | |
| rm -f "$GIT_DIR"/TAG_TMP.asc "$GIT_DIR"/TAG_FINALMSG | |
| if [ "$signed" ]; then | |
| gpg -bsa -u "$username" "$GIT_DIR"/TAG_TMP && | |
| cat "$GIT_DIR"/TAG_TMP.asc >>"$GIT_DIR"/TAG_TMP || | |
| die "failed to sign the tag with GPG." | |
| fi | |
| object=$(git-mktag < "$GIT_DIR"/TAG_TMP) | |
| fi | |
| git update-ref "refs/tags/$name" "$object" "$prev" |