From 5c02350fa03d60ca41a76aca36e788db86cfabf9 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 15 May 2024 09:36:12 +0200 Subject: [PATCH] scripts/setlocalversion: sync with linux v6.9 The changes upstream since the last sync (2ed1b242ab2 "scripts/setlocalversion: sync with linux 5.8") are (5) 548b8b5168c9 scripts/setlocalversion: make git describe output more reliable 77a88274dc1a kbuild: replace LANG=C with LC_ALL=C 2a73cce2dad3 scripts/setlocalversion: remove mercurial, svn and git-svn supports a2be76a352f1 scripts/setlocalversion: remove workaround for old make-kpkg ffaf62a8050b scripts/setlocalversion: add more comments to -dirty flag detection 630ff0faf84e scripts/setlocalversion: factor out 12-chars hash construction 042da426f8eb scripts/setlocalversion: simplify the short version part 5df99bec210a scripts/setlocalversion: fix a bug when LOCALVERSION is empty (1) 7d153696e5db kbuild: do not include include/config/auto.conf from shell scripts (2) 129ab0d2d9f3 kbuild: do not quote string values in include/config/auto.conf f6e09b07cc12 kbuild: do not put .scmversion into the source tarball 992ebfab2a75 setlocalversion: simplify the construction of the short version 75280bdf49b2 setlocalversion: make indentation shallower (3) ec31f868ec67 setlocalversion: absorb $(KERNELVERSION) eed36d775177 setlocalversion: clean up the construction of version output (4) 6ab7e1f95e96 setlocalversion: use only the correct release tag for git-describe 05e96e96a315 kbuild: use git-archive for source package creation 3354c64d4184 scripts/setlocalversion: clean up stale comment 01e89a4acefc scripts/setlocalversion: also consider annotated tags of the form vx.y.z-${file_localversion} The only thing U-Boot has been applying on top was to deal with not sourcing include/config/auto.conf but instead using awk to extract the right value. Commit (1) did a very similar thing upstream, so we no longer need to do that. However, upstream then went a step further (2) and changed the convention for what goes into auto.conf, so RHS no longer contain double-quotes. That commit thus changed the sed pattern to no longer match those quotes, but as U-Boot has not yet adopted that change, we have to deal with that. In order to be a little forward-compatible, I did that in a way that should work both ways: # version string from CONFIG_LOCALVERSION -config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' include/config/auto.conf) +config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' include/config/auto.conf | tr -d '"') Furthermore, (3) now requires that there is an appropriate KERNELVERSION environment variable set. One way to deal with that would be to just modify the script to use UBOOTVERSION instead, but for now I've instead opted to let the Makefile provide KERNELVERSION=$(UBOOTVERSION) to keep the setlocalversion changes minimal. That variable is further put to use in (4). Note that the logic for mapping *VERSION -> [upstream annotated tag to look for] works unchanged in U-Boot for the current versioning scheme 20XX.YY(-rcN)?. My motivation for wanting to do this sync is to get (4) and (5), in order to get the setlocalversion output both more predictable and consistent across different build environments, i.e. independent of random local .gitconfig settings, total number of git objects and/or existence of unrelated tags (possibly from some tracked fork). Signed-off-by: Rasmus Villemoes --- Makefile | 5 +- scripts/setlocalversion | 226 ++++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 115 deletions(-) diff --git a/Makefile b/Makefile index efaf24e58e..14acea9c6b 100644 --- a/Makefile +++ b/Makefile @@ -1898,8 +1898,11 @@ $(filter-out tools, $(u-boot-dirs)): tools # is "yes"), so compile examples after U-Boot is compiled. examples: $(filter-out examples, $(u-boot-dirs)) +# The setlocalversion script comes from linux and expects a +# KERNELVERSION variable in the environment for figuring out which +# annotated tags are relevant. Pass UBOOTVERSION. define filechk_uboot.release - echo "$(UBOOTVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" + KERNELVERSION=$(UBOOTVERSION) $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree) endef # Store (new) UBOOTRELEASE string in include/config/uboot.release diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 4a63143706..dbe048210d 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-2.0 # # This scripts adds local version information from the version -# control systems git, mercurial (hg) and subversion (svn). +# control system git. # # If something goes wrong, send a mail the kernel build mailinglist # (see MAINTAINERS) and CC Nico Schottelius @@ -11,16 +11,17 @@ # usage() { - echo "Usage: $0 [--save-scmversion] [srctree]" >&2 + echo "Usage: $0 [--no-local] [srctree]" >&2 exit 1 } -scm_only=false -srctree=. -if test "$1" = "--save-scmversion"; then - scm_only=true +no_local=false +if test "$1" = "--no-local"; then + no_local=true shift fi + +srctree=. if test $# -gt 0; then srctree=$1 shift @@ -31,96 +32,98 @@ fi scm_version() { - local short - short=false + 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 -e .scmversion; then - cat .scmversion + + if test -n "$(git rev-parse --show-cdup 2>/dev/null)"; then return fi - if test "$1" = "--short"; then - short=true - fi - # Check for git and a git repo. - if test -z "$(git rev-parse --show-cdup 2>/dev/null)" && - head=$(git rev-parse --verify --short HEAD 2>/dev/null); then - - # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore - # it, because this version is defined in the top level Makefile. - if [ -z "$(git describe --exact-match 2>/dev/null)" ]; 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 a tagged commit (like - # "v2.6.30-rc5-302-g72357d5"), we pretty print it. - if atag="$(git describe 2>/dev/null)"; then - echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' - - # If we don't have a tag at all we print -g{commitish}. - else - printf '%s%s' -g $head - fi - fi + if ! head=$(git rev-parse --verify HEAD 2>/dev/null); then + return + fi - # Is this git on svn? - if git config --get svn-remote.svn.url >/dev/null; then - printf -- '-svn%s' "$(git svn find-rev $head)" - 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 - # Check for uncommitted changes. - # 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 - } | grep -qvE '^(.. )?scripts/package'; then - printf '%s' -dirty - 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 - # All done with git - return + # 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 - # Check for mercurial and a mercurial repo. - if test -d .hg && hgid=$(hg id 2>/dev/null); then - # Do we have an tagged version? If so, latesttagdistance == 1 - if [ "$(hg log -r . --template '{latesttagdistance}')" = "1" ]; then - id=$(hg log -r . --template '{latesttag}') - printf '%s%s' -hg "$id" - else - tag=$(printf '%s' "$hgid" | cut -d' ' -f2) - if [ -z "$tag" -o "$tag" = tip ]; then - id=$(printf '%s' "$hgid" | sed 's/[+ ].*//') - printf '%s%s' -hg "$id" - 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 - # Are there uncommitted changes? - # These are represented by + after the changeset id. - case "$hgid" in - *+|*+\ *) printf '%s' -dirty ;; - esac + # Add -g and exactly 12 hex chars. + printf '%s%s' -g "$(echo $head | cut -c1-12)" + fi - # All done with mercurial + if ${no_dirty}; then return fi - # Check for svn and a svn repo. - if rev=$(LANG= LC_ALL= LC_MESSAGES=C svn info 2>/dev/null | grep '^Last Changed Rev'); then - rev=$(echo $rev | awk '{print $NF}') - printf -- '-svn%s' "$rev" - - # All done with svn - return + # 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 } @@ -141,48 +144,43 @@ collect_files() echo "$res" } -if $scm_only; then - if test ! -e .scmversion; then - res=$(scm_version) - echo "$res" >.scmversion - fi - exit -fi - -if test -e include/config/auto.conf; then - # We are interested only in CONFIG_LOCALVERSION and - # CONFIG_LOCALVERSION_AUTO, so extract these in a safe - # way (i.e. w/o sourcing auto.conf) - # xargs echo removes quotes - CONFIG_LOCALVERSION=`cat include/config/auto.conf | awk -F '=' '/^CONFIG_LOCALVERSION=/ {print $2}' | xargs echo` - CONFIG_LOCALVERSION_AUTO=`cat include/config/auto.conf | awk -F '=' '/^CONFIG_LOCALVERSION_AUTO=/ {print $2}' | xargs echo` -else - echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2 +if [ -z "${KERNELVERSION}" ]; then + echo "KERNELVERSION is not set" >&2 exit 1 fi # localversion* files in the build and source directory -res="$(collect_files localversion*)" +file_localversion="$(collect_files localversion*)" if test ! "$srctree" -ef .; then - res="$res$(collect_files "$srctree"/localversion*)" + 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 -# CONFIG_LOCALVERSION and LOCALVERSION (if set) -res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" +# version string from CONFIG_LOCALVERSION +config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' include/config/auto.conf | tr -d '"') -# scm version string if not at a tagged commit -if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then +# 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 - res="$res$(scm_version)" -else - # 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) and - # LOCALVERSION= is not specified - if test "${LOCALVERSION+set}" != "set"; then - scm=$(scm_version --short) - res="$res${scm:++}" - fi + 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 "$res" +echo "${KERNELVERSION}${file_localversion}${config_localversion}${LOCALVERSION}${scm_version}" -- 2.39.5