|
| 1 | +#!/bin/sh |
| 2 | + |
| 3 | +# Copyright (c) 2018 Anton Semjonov |
| 4 | +# Licensed under the MIT License |
| 5 | + |
| 6 | +# This script prints version information for a project managed with Git when |
| 7 | +# executed in a shell. It works from checked-out repositories or downloaded |
| 8 | +# archives alike. For more information see https://github.com/ansemjo/version.sh |
| 9 | + |
| 10 | +# -- SYNOPSIS -- Copy this script to your project root and add the line |
| 11 | +# 'version.sh export-subst' to your .gitattributes file, creating it if it does |
| 12 | +# not exist. Commit both files, try running 'sh ./version.sh' and use annotated |
| 13 | +# Git tags to track your versions. |
| 14 | + |
| 15 | +# Ignore certain shellcheck warnings: |
| 16 | +# - '$Format..' looks like a variable in single-quotes but this is |
| 17 | +# necessary so it does _not_ expand when interpreted by the shell |
| 18 | +# - backslash before a literal newline is a portable way |
| 19 | +# to insert newlines with sed |
| 20 | +# shellcheck disable=SC2016,SC1004 |
| 21 | + |
| 22 | +# Magic! These strings will be substituted by 'git archive': |
| 23 | +COMMIT='$Format:%H$' |
| 24 | +REFS='$Format:%D$' |
| 25 | + |
| 26 | +# Fallback values: |
| 27 | +FALLBACK_VERSION='commit' |
| 28 | +FALLBACK_COMMIT='unknown' |
| 29 | + |
| 30 | +# Revision and commit hash seperators in 'describe' string: |
| 31 | +REVISION_SEPERATOR="${REVISION_SEPERATOR:--}" |
| 32 | +COMMIT_SEPERATOR="${COMMIT_SEPERATOR:--g}" |
| 33 | + |
| 34 | +# Check if variables contain substituted values? |
| 35 | +subst() { test -n "${COMMIT##\$Format*}" && test -n "${REFS##\$Format*}"; } |
| 36 | + |
| 37 | +# Check if git and repository information is available? |
| 38 | +hasgit() { |
| 39 | + command -v git >/dev/null && { test -r .git || git rev-parse 2>/dev/null; }; |
| 40 | +} |
| 41 | + |
| 42 | +# Parse the %D reflist in $REFS to get a tag or branch name: |
| 43 | +refparse() { |
| 44 | + # try to find a tag: |
| 45 | + tag=$(echo "$REFS" | sed -ne 's/.*tag: \([^,]*\).*/\1/p'); |
| 46 | + test -n "$tag" && echo "$tag" && return 0; |
| 47 | + # try to find a branch name: |
| 48 | + branch=$(echo "$REFS" | sed -e 's/HEAD -> //' -e 's/, /\ |
| 49 | +/' | sed -ne '/^[a-z0-9._-]*$/p' | sed -n '1p'); |
| 50 | + test -n "$branch" && echo "$branch" && return 0; |
| 51 | + # nothing found, no tags and not a branch tip? |
| 52 | + return 1; |
| 53 | +} |
| 54 | + |
| 55 | +# Try to get commit and version information with git: |
| 56 | +gitcommit() { |
| 57 | + hasgit && git describe --always --abbrev=0 --match '^$' --dirty; |
| 58 | +} |
| 59 | +gitversion() { |
| 60 | + hasgit && { |
| 61 | + { |
| 62 | + # try to use 'describe': |
| 63 | + V=$(git describe 2>/dev/null) && \ |
| 64 | + echo "$V" | sed 's/-\([0-9]*\)-g.*/'"$REVISION_SEPERATOR"'\1/'; |
| 65 | + } || { |
| 66 | + # or count the number of commits otherwise: |
| 67 | + C=$(git rev-list --count HEAD) && \ |
| 68 | + printf '0.0.0%s%s' "$REVISION_SEPERATOR" "$C"; |
| 69 | + }; |
| 70 | + }; |
| 71 | +} |
| 72 | + |
| 73 | +# Wrappers to return version and commit (substituted -> git info -> fallback): |
| 74 | +version() { subst && refparse || gitversion || echo "$FALLBACK_VERSION"; } |
| 75 | +commit() { subst && echo "$COMMIT" || gitcommit || echo "$FALLBACK_COMMIT"; } |
| 76 | +describe() { printf '%s%s%.7s\n' "$(version)" "$COMMIT_SEPERATOR" "$(commit)"; } |
| 77 | + |
| 78 | +# Parse commandline argument: |
| 79 | +case "$1" in |
| 80 | + version) version ;; |
| 81 | + commit) commit ;; |
| 82 | + describe) describe ;; |
| 83 | + json) |
| 84 | + printf '{"version":"%s","commit":"%s","describe":"%s"}\n' \ |
| 85 | + "$(version)" "$(commit)" "$(describe)" ;; |
| 86 | + help) |
| 87 | + printf '%s [version|commit|describe|json]\n' "$0" ;; |
| 88 | + *) |
| 89 | + printf 'version : %s\ncommit : %s\n' "$(version)" "$(commit)" ;; |
| 90 | +esac |
0 commit comments