
Commit 6ab7e1f95e
("setlocalversion: use only the correct release
tag for git-describe") was absolutely correct to limit which annotated
tags would be used to compute the -01234-gabcdef suffix. Otherwise, if
some random annotated tag exists closer to HEAD than the vX.Y.Z one,
the commit count would be too low.
However, since the version string always includes the
${file_localversion} part, now the problem is that the count can be
too high. For example, building an 6.4.6-rt8 kernel with a few patches
on top, I currently get
$ make -s kernelrelease
6.4.6-rt8-00128-gd78b7f406397
But those 128 commits include the 100 commits that are in
v6.4.6..v6.4.6-rt8, so this is somewhat misleading.
Amend the logic so that, in addition to the linux-next consideration,
the script also looks for a tag corresponding to the 6.4.6-rt8 part of
what will become the `uname -r` string. With this patch (so 29 patches
on top of v6.4.6-rt8), one instead gets
$ make -s kernelrelease
6.4.6-rt8-00029-gd533209291a2
While there, note that the line
git describe --exact-match --match=$tag $tag 2>/dev/null
obviously asks if $tag is an annotated tag, but it does not actually
tell if the commit pointed to has any relation to HEAD. So remove both
uses of --exact-match, and instead just ask if the description
generated is identical to the tag we provided. Since we then already
have the result of
git describe --match=$tag
we also end up reducing the number of times we invoke "git describe".
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
4.6 KiB
Executable File
#!/bin/sh
SPDX-License-Identifier: GPL-2.0
This scripts adds local version information from the version
control system git.
If something goes wrong, send a mail the kernel build mailinglist
(see MAINTAINERS) and CC Nico Schottelius
<nico-linuxsetlocalversion -at- schottelius.org>.
usage() { echo "Usage: $0 [--no-local] [srctree]" >&2 exit 1 }
no_local=false if test "$1" = "--no-local"; then no_local=true shift fi
srctree=. if test $# -gt 0; then srctree=$1 shift fi if test $# -gt 0 -o ! -d "$srctree"; then usage fi
scm_version() { local short=false local no_dirty=false local tag
while [ $# -gt 0 ];
do
case "$1" in
--short)
short=true;;
--no-dirty)
no_dirty=true;;
esac
shift
done
cd "$srctree"
if test -n "$(git rev-parse --show-cdup 2>/dev/null)"; then
return
fi
if ! head=$(git rev-parse --verify HEAD 2>/dev/null); then
return
fi
# mainline kernel: 6.2.0-rc5 -> v6.2-rc5
# stable kernel: 6.1.7 -> v6.1.7
version_tag=v$(echo "${KERNELVERSION}" | sed -E 's/^([0-9]+\.[0-9]+)\.0(.*)$/\1\2/')
# If a localversion* file exists, and the corresponding
# annotated tag exists and is an ancestor of HEAD, use
# it. This is the case in linux-next.
tag=${file_localversion#-}
desc=
if [ -n "${tag}" ]; then
desc=$(git describe --match=$tag 2>/dev/null)
fi
# Otherwise, if a localversion* file exists, and the tag
# obtained by appending it to the tag derived from
# KERNELVERSION exists and is an ancestor of HEAD, use
# it. This is e.g. the case in linux-rt.
if [ -z "${desc}" ] && [ -n "${file_localversion}" ]; then
tag="${version_tag}${file_localversion}"
desc=$(git describe --match=$tag 2>/dev/null)
fi
# Otherwise, default to the annotated tag derived from KERNELVERSION.
if [ -z "${desc}" ]; then
tag="${version_tag}"
desc=$(git describe --match=$tag 2>/dev/null)
fi
# If we are at the tagged commit, we ignore it because the version is
# well-defined.
if [ "${tag}" != "${desc}" ]; then
# If only the short version is requested, don't bother
# running further git commands
if $short; then
echo "+"
return
fi
# If we are past the tagged commit, we pretty print it.
# (like 6.1.0-14595-g292a089d78d3)
if [ -n "${desc}" ]; then
echo "${desc}" | awk -F- '{printf("-%05d", $(NF-1))}'
fi
# Add -g and exactly 12 hex chars.
printf '%s%s' -g "$(echo $head | cut -c1-12)"
fi
if ${no_dirty}; then
return
fi
# Check for uncommitted changes.
# This script must avoid any write attempt to the source tree, which
# might be read-only.
# You cannot use 'git describe --dirty' because it tries to create
# .git/index.lock .
# First, with git-status, but --no-optional-locks is only supported in
# git >= 2.14, so fall back to git-diff-index if it fails. Note that
# git-diff-index does not refresh the index, so it may give misleading
# results.
# See git-update-index(1), git-diff-index(1), and git-status(1).
if {
git --no-optional-locks status -uno --porcelain 2>/dev/null ||
git diff-index --name-only HEAD
} | read dummy; then
printf '%s' -dirty
fi
}
collect_files() { local file res=
for file; do
case "$file" in
*\~*)
continue
;;
esac
if test -e "$file"; then
res="$res$(cat "$file")"
fi
done
echo "$res"
}
if [ -z "${KERNELVERSION}" ]; then echo "KERNELVERSION is not set" >&2 exit 1 fi
localversion* files in the build and source directory
file_localversion="$(collect_files localversion*)" if test ! "$srctree" -ef .; then file_localversion="${file_localversion}$(collect_files "$srctree"/localversion*)" fi
if ${no_local}; then echo "${KERNELVERSION}$(scm_version --no-dirty)" exit 0 fi
if ! test -e include/config/auto.conf; then echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2 exit 1 fi
version string from CONFIG_LOCALVERSION
config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=(.*)$/\1/p' include/config/auto.conf)
scm version string if not at the kernel version tag or at the file_localversion
if grep -q "^CONFIG_LOCALVERSION_AUTO=y$" include/config/auto.conf; then # full scm version string scm_version="$(scm_version)" elif [ "${LOCALVERSION+set}" != "set" ]; then # If the variable LOCALVERSION is not set, append a plus # sign if the repository is not in a clean annotated or # signed tagged state (as git describe only looks at signed # or annotated tags - git tag -a/-s). # # If the variable LOCALVERSION is set (including being set # to an empty string), we don't want to append a plus sign. scm_version="$(scm_version --short)" fi
echo "${KERNELVERSION}${file_localversion}${config_localversion}${LOCALVERSION}${scm_version}"