git/GIT-VERSION-GEN
Patrick Steinhardt f6a2efdc9b GIT-VERSION-GEN: allow running without input and output files
The GIT-VERSION-GEN script requires an input file containing formatting
directives to be replaced as well as an output file that will get
overwritten in case the file contents have changed. When computing the
project version for Meson we don't want to have either though:

  - We only want to compute the version without anything else, but don't
    have an input file that would match that exact format. While we
    could of course introduce a new file just for that usecase, it feels
    suboptimal to add another file every time we want to have a slightly
    different format for versioned data.

  - The computed version needs to be read from stdout so that Meson can
    wire it up for the project.

Extend the script to handle both usecases by recognizing `--format=` as
alternative to providing an input path and by writing to stdout in case
no output file was given.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-01-22 12:37:32 -08:00

107 lines
2.4 KiB
Bash
Executable File

#!/bin/sh
DEF_VER=v2.48.0
LF='
'
if test "$#" -lt 2 || test "$#" -gt 3
then
echo >&2 "USAGE: $0 <SOURCE_DIR> (--format=<STRING>|<INPUT>) [<OUTPUT>]"
exit 1
fi
SOURCE_DIR="$1"
case "$2" in
--format=*)
INPUT="${2#--format=}"
;;
*)
if ! test -f "$2"
then
echo >&2 "Input is not a file: $2"
exit 1
fi
INPUT=$(cat "$2")
;;
esac
OUTPUT="$3"
# Protect us from reading Git version information outside of the Git directory
# in case it is not a repository itself, but embedded in an unrelated
# repository.
GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.."
export GIT_CEILING_DIRECTORIES
if test -z "$GIT_VERSION"
then
# First see if there is a version file (included in release tarballs),
# then try git-describe, then default.
if test -f "$SOURCE_DIR"/version
then
VN=$(cat "$SOURCE_DIR"/version) || VN="$DEF_VER"
elif {
test -d "$SOURCE_DIR/.git" ||
test -d "${GIT_DIR:-.git}" ||
test -f "$SOURCE_DIR"/.git;
} &&
VN=$(git -C "$SOURCE_DIR" describe --dirty --match="v[0-9]*" 2>/dev/null) &&
case "$VN" in
*$LF*) (exit 1) ;;
esac
then
VN=$(echo "$VN" | sed -e 's/-/./g');
else
VN="$DEF_VER"
fi
GIT_VERSION=$(expr "$VN" : v*'\(.*\)')
fi
if test -z "$GIT_BUILT_FROM_COMMIT"
then
GIT_BUILT_FROM_COMMIT=$(git -C "$SOURCE_DIR" rev-parse -q --verify HEAD 2>/dev/null)
fi
if test -z "$GIT_DATE"
then
GIT_DATE=$(git -C "$SOURCE_DIR" show --quiet --format='%as' 2>/dev/null)
fi
if test -z "$GIT_USER_AGENT"
then
GIT_USER_AGENT="git/$GIT_VERSION"
fi
# While released Git versions only have three numbers, development builds also
# have a fourth number that corresponds to the number of patches since the last
# release.
read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trailing <<EOF
$(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ')
EOF
REPLACED=$(printf "%s" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \
-e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \
-e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \
-e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \
-e "s|@GIT_PATCH_LEVEL@|$GIT_PATCH_LEVEL|" \
-e "s|@GIT_BUILT_FROM_COMMIT@|$GIT_BUILT_FROM_COMMIT|" \
-e "s|@GIT_USER_AGENT@|$GIT_USER_AGENT|" \
-e "s|@GIT_DATE@|$GIT_DATE|"
)
if test -z "$OUTPUT"
then
printf "%s\n" "$REPLACED"
else
printf "%s\n" "$REPLACED" >"$OUTPUT".$$+
if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null
then
mv "$OUTPUT".$$+ "$OUTPUT"
else
rm "$OUTPUT".$$+
fi
fi