blob: c1ece5ac9b22eb2928c60cffe0d1d56d65a9b339 [file] [log] [blame]
Wolfgang Denk4d1d9a32006-02-21 17:33:04 +01001#!/bin/sh
Rasmus Villemoesf62d0462020-08-25 17:28:39 +02002# SPDX-License-Identifier: GPL-2.0
Kyle Moffett787fb372011-12-16 11:14:40 +00003#
4# This scripts adds local version information from the version
Rasmus Villemoes86354212024-05-15 09:36:12 +02005# control system git.
Kyle Moffett787fb372011-12-16 11:14:40 +00006#
Masahiro Yamada422633e2014-08-22 19:42:28 +09007# If something goes wrong, send a mail the kernel build mailinglist
8# (see MAINTAINERS) and CC Nico Schottelius
9# <nico-linuxsetlocalversion -at- schottelius.org>.
10#
Kyle Moffett787fb372011-12-16 11:14:40 +000011#
Wolfgang Denk4d1d9a32006-02-21 17:33:04 +010012
Tom Rini0f7dfbe2025-05-26 07:35:10 -060013set -e
14
Wolfgang Denk4d1d9a32006-02-21 17:33:04 +010015usage() {
Rasmus Villemoes86354212024-05-15 09:36:12 +020016 echo "Usage: $0 [--no-local] [srctree]" >&2
Wolfgang Denk4d1d9a32006-02-21 17:33:04 +010017 exit 1
18}
19
Rasmus Villemoes86354212024-05-15 09:36:12 +020020no_local=false
21if test "$1" = "--no-local"; then
22 no_local=true
Kyle Moffett787fb372011-12-16 11:14:40 +000023 shift
24fi
Rasmus Villemoes86354212024-05-15 09:36:12 +020025
26srctree=.
Kyle Moffett787fb372011-12-16 11:14:40 +000027if test $# -gt 0; then
28 srctree=$1
29 shift
30fi
31if test $# -gt 0 -o ! -d "$srctree"; then
32 usage
33fi
34
Tom Rini0f7dfbe2025-05-26 07:35:10 -060035try_tag() {
36 tag="$1"
37
38 # Is $tag an annotated tag?
39 if [ "$(git cat-file -t "$tag" 2> /dev/null)" != tag ]; then
40 return
41 fi
42
43 # Is it an ancestor of HEAD, and if so, how many commits are in $tag..HEAD?
44 # shellcheck disable=SC2046 # word splitting is the point here
45 set -- $(git rev-list --count --left-right "$tag"...HEAD 2> /dev/null)
46
47 # $1 is 0 if and only if $tag is an ancestor of HEAD. Use
48 # string comparison, because $1 is empty if the 'git rev-list'
49 # command somehow failed.
50 if [ "$1" != 0 ]; then
51 return
52 fi
53
54 # $2 is the number of commits in the range $tag..HEAD, possibly 0.
55 count="$2"
56}
57
Kyle Moffett787fb372011-12-16 11:14:40 +000058scm_version()
59{
Rasmus Villemoes86354212024-05-15 09:36:12 +020060 local short=false
61 local no_dirty=false
62 local tag
63
64 while [ $# -gt 0 ];
65 do
66 case "$1" in
67 --short)
68 short=true;;
69 --no-dirty)
70 no_dirty=true;;
71 esac
72 shift
73 done
Kyle Moffett787fb372011-12-16 11:14:40 +000074
75 cd "$srctree"
Marek Vasutb2970c02025-03-02 19:30:28 +010076 if test -e .scmversion; then
77 cat .scmversion
78 return
79 fi
Rasmus Villemoes86354212024-05-15 09:36:12 +020080
81 if test -n "$(git rev-parse --show-cdup 2>/dev/null)"; then
Kyle Moffett787fb372011-12-16 11:14:40 +000082 return
83 fi
Rasmus Villemoes86354212024-05-15 09:36:12 +020084
85 if ! head=$(git rev-parse --verify HEAD 2>/dev/null); then
86 return
Kyle Moffett787fb372011-12-16 11:14:40 +000087 fi
88
Rasmus Villemoes86354212024-05-15 09:36:12 +020089 # mainline kernel: 6.2.0-rc5 -> v6.2-rc5
90 # stable kernel: 6.1.7 -> v6.1.7
91 version_tag=v$(echo "${KERNELVERSION}" | sed -E 's/^([0-9]+\.[0-9]+)\.0(.*)$/\1\2/')
Kyle Moffett787fb372011-12-16 11:14:40 +000092
Tom Rini0f7dfbe2025-05-26 07:35:10 -060093 # try_tag initializes count if the tag is usable.
94 count=
95
Rasmus Villemoes86354212024-05-15 09:36:12 +020096 # If a localversion* file exists, and the corresponding
97 # annotated tag exists and is an ancestor of HEAD, use
98 # it. This is the case in linux-next.
Tom Rini0f7dfbe2025-05-26 07:35:10 -060099 if [ -n "${file_localversion#-}" ] ; then
100 try_tag "${file_localversion#-}"
Rasmus Villemoes86354212024-05-15 09:36:12 +0200101 fi
Kyle Moffett787fb372011-12-16 11:14:40 +0000102
Rasmus Villemoes86354212024-05-15 09:36:12 +0200103 # Otherwise, if a localversion* file exists, and the tag
104 # obtained by appending it to the tag derived from
105 # KERNELVERSION exists and is an ancestor of HEAD, use
106 # it. This is e.g. the case in linux-rt.
Tom Rini0f7dfbe2025-05-26 07:35:10 -0600107 if [ -z "${count}" ] && [ -n "${file_localversion}" ]; then
108 try_tag "${version_tag}${file_localversion}"
Rasmus Villemoes86354212024-05-15 09:36:12 +0200109 fi
Kyle Moffett787fb372011-12-16 11:14:40 +0000110
Rasmus Villemoes86354212024-05-15 09:36:12 +0200111 # Otherwise, default to the annotated tag derived from KERNELVERSION.
Tom Rini0f7dfbe2025-05-26 07:35:10 -0600112 if [ -z "${count}" ]; then
113 try_tag "${version_tag}"
Rasmus Villemoes86354212024-05-15 09:36:12 +0200114 fi
Kyle Moffett787fb372011-12-16 11:14:40 +0000115
Tom Rini0f7dfbe2025-05-26 07:35:10 -0600116 # If we are at the tagged commit, we ignore it because the
117 # version is well-defined. If none of the attempted tags exist
118 # or were usable, $count is still empty.
119 if [ -z "${count}" ] || [ "${count}" -gt 0 ]; then
Kyle Moffett787fb372011-12-16 11:14:40 +0000120
Rasmus Villemoes86354212024-05-15 09:36:12 +0200121 # If only the short version is requested, don't bother
122 # running further git commands
123 if $short; then
124 echo "+"
125 return
Kyle Moffett787fb372011-12-16 11:14:40 +0000126 fi
Tom Rini0f7dfbe2025-05-26 07:35:10 -0600127
Rasmus Villemoes86354212024-05-15 09:36:12 +0200128 # If we are past the tagged commit, we pretty print it.
129 # (like 6.1.0-14595-g292a089d78d3)
Tom Rini0f7dfbe2025-05-26 07:35:10 -0600130 if [ -n "${count}" ]; then
131 printf "%s%05d" "-" "${count}"
Kyle Moffett787fb372011-12-16 11:14:40 +0000132 fi
133
Rasmus Villemoes86354212024-05-15 09:36:12 +0200134 # Add -g and exactly 12 hex chars.
Tom Rini0f7dfbe2025-05-26 07:35:10 -0600135 printf '%s%.12s' -g "$head"
Rasmus Villemoes86354212024-05-15 09:36:12 +0200136 fi
Kyle Moffett787fb372011-12-16 11:14:40 +0000137
Rasmus Villemoes86354212024-05-15 09:36:12 +0200138 if ${no_dirty}; then
Kyle Moffett787fb372011-12-16 11:14:40 +0000139 return
Wolfgang Denk4d1d9a32006-02-21 17:33:04 +0100140 fi
Mike Frysingerbfac87a2008-04-08 14:00:57 -0400141
Rasmus Villemoes86354212024-05-15 09:36:12 +0200142 # Check for uncommitted changes.
143 # This script must avoid any write attempt to the source tree, which
144 # might be read-only.
145 # You cannot use 'git describe --dirty' because it tries to create
146 # .git/index.lock .
147 # First, with git-status, but --no-optional-locks is only supported in
148 # git >= 2.14, so fall back to git-diff-index if it fails. Note that
149 # git-diff-index does not refresh the index, so it may give misleading
150 # results.
151 # See git-update-index(1), git-diff-index(1), and git-status(1).
152 if {
153 git --no-optional-locks status -uno --porcelain 2>/dev/null ||
154 git diff-index --name-only HEAD
155 } | read dummy; then
156 printf '%s' -dirty
Kyle Moffett787fb372011-12-16 11:14:40 +0000157 fi
158}
159
160collect_files()
161{
Rasmus Villemoesf62d0462020-08-25 17:28:39 +0200162 local file res=
Kyle Moffett787fb372011-12-16 11:14:40 +0000163
164 for file; do
165 case "$file" in
166 *\~*)
167 continue
168 ;;
169 esac
170 if test -e "$file"; then
171 res="$res$(cat "$file")"
172 fi
173 done
174 echo "$res"
175}
176
Rasmus Villemoes86354212024-05-15 09:36:12 +0200177if [ -z "${KERNELVERSION}" ]; then
178 echo "KERNELVERSION is not set" >&2
Masahiro Yamada422633e2014-08-22 19:42:28 +0900179 exit 1
180fi
Kyle Moffett787fb372011-12-16 11:14:40 +0000181
182# localversion* files in the build and source directory
Rasmus Villemoes86354212024-05-15 09:36:12 +0200183file_localversion="$(collect_files localversion*)"
Kyle Moffett787fb372011-12-16 11:14:40 +0000184if test ! "$srctree" -ef .; then
Rasmus Villemoes86354212024-05-15 09:36:12 +0200185 file_localversion="${file_localversion}$(collect_files "$srctree"/localversion*)"
186fi
187
188if ${no_local}; then
189 echo "${KERNELVERSION}$(scm_version --no-dirty)"
190 exit 0
191fi
192
193if ! test -e include/config/auto.conf; then
194 echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2
195 exit 1
Kyle Moffett787fb372011-12-16 11:14:40 +0000196fi
197
Rasmus Villemoes86354212024-05-15 09:36:12 +0200198# version string from CONFIG_LOCALVERSION
199config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' include/config/auto.conf | tr -d '"')
Kyle Moffett787fb372011-12-16 11:14:40 +0000200
Rasmus Villemoes86354212024-05-15 09:36:12 +0200201# scm version string if not at the kernel version tag or at the file_localversion
202if grep -q "^CONFIG_LOCALVERSION_AUTO=y$" include/config/auto.conf; then
Kyle Moffett787fb372011-12-16 11:14:40 +0000203 # full scm version string
Rasmus Villemoes86354212024-05-15 09:36:12 +0200204 scm_version="$(scm_version)"
205elif [ "${LOCALVERSION+set}" != "set" ]; then
206 # If the variable LOCALVERSION is not set, append a plus
207 # sign if the repository is not in a clean annotated or
208 # signed tagged state (as git describe only looks at signed
209 # or annotated tags - git tag -a/-s).
210 #
211 # If the variable LOCALVERSION is set (including being set
212 # to an empty string), we don't want to append a plus sign.
213 scm_version="$(scm_version --short)"
Wolfgang Denk4d1d9a32006-02-21 17:33:04 +0100214fi
Mike Frysingerbfac87a2008-04-08 14:00:57 -0400215
Rasmus Villemoes86354212024-05-15 09:36:12 +0200216echo "${KERNELVERSION}${file_localversion}${config_localversion}${LOCALVERSION}${scm_version}"