]> sourceware.org Git - systemtap.git/blame - git_version.sh
PR32209: Improve the fix per bugzilla comment #6
[systemtap.git] / git_version.sh
CommitLineData
c0f9d4b0
FCE
1#!/bin/sh
2#
3# Generate some basic versioning information which can be piped to a header.
4#
5# Copyright (c) 2006-2007 Luc Verhaegen <libv@skynet.be>
2899dcf6
FCE
6# Copyright (C) 2007-2008 Hans Ulrich Niedermann <hun@n-dimensional.de>
7# Copyright (C) 2021 Lawrence Sebald
c0f9d4b0
FCE
8#
9# Permission is hereby granted, free of charge, to any person obtaining a
10# copy of this software and associated documentation files (the "Software"),
11# to deal in the Software without restriction, including without limitation
12# the rights to use, copy, modify, merge, publish, distribute, sublicense,
13# and/or sell copies of the Software, and to permit persons to whom the
14# Software is furnished to do so, subject to the following conditions:
15#
16# The above copyright notice and this permission notice shall be included in
17# all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25# OTHER DEALINGS IN THE SOFTWARE.
26#
27# This script is based on the one written for xf86-video-unichrome by
28# Luc Verhaegen, but was rewritten almost completely by Hans Ulrich
29# Niedermann. The script contains a few bug fixes from Egbert Eich,
2899dcf6
FCE
30# Matthias Hopf, Joerg Sonnenberger, and possibly others. Later modified
31# for Sylverant by Lawrence Sebald.
c0f9d4b0
FCE
32#
33# The author thanks the nice people on #git for the assistance.
34#
35# Simple testing of this script:
36# /sbin/busybox sh git_version.sh --example > moo.c \
37# && gcc -Wall -Wextra -Wno-unused -o moo moo.c \
38# && ./moo
39# (bash should also do)
40#
41# For how to hook this up to your automake- and/or imake-based build
42# system, best take a look at how the RadeonHD.am and/or RadeonHD.tmpl
43# work in the xf86-video-radeonhd build system. For non-recursive make,
44# you can probably make things a little bit simpler.
45#
2899dcf6
FCE
46# Requires git >= 1.3.0 for the 'git foo' (with space) syntax,
47# and git >= 1.4 for some specific commands.
c0f9d4b0
FCE
48
49# Help messages
50USAGE="[<option>...]"
51LONG_USAGE="\
52Options:
53 -h, --help Print this help message.
54
55 -k, --keep-if-no-repo Keep old output file if no git repo found.
56 -o, --output FILENAME Set output file name.
57 -q, --quiet Quiet output.
58 -s, --srcdir DIRNAME Set source tree dir name.
59 -x, --example Print complete example program."
60
61# The caller may have set these for us
62SED="${SED-sed}"
2899dcf6 63GIT="${GIT-git}"
c0f9d4b0
FCE
64
65# Initialize
2899dcf6 66working_dir=`pwd`
c0f9d4b0
FCE
67
68# Who am I?
2899dcf6 69self=`basename "$0"`
c0f9d4b0
FCE
70
71# Defaults
72ifndef_symbol="GIT_VERSION_H"
73outfile="-"
74print_example=false
75keep_if_no_repo=no
76quiet=false
2899dcf6 77srcdir=`pwd`
c0f9d4b0
FCE
78
79# Parse command line parameter, affecting defaults
80while [ "x$1" != "x" ]
81do
82 case "$1" in
83 -x|--example)
84 print_example=:
85 ;;
86 -o|--output)
87 if shift; then
88 outfile="$1"
89 if [ "x$outfile" = "x-" ]; then
90 : # keep default ifndef_symbol
91 else
92 ifndef_symbol=`basename "$outfile" | $SED 's|\.|_|g; s|[^A-Za-z0-9_]||g' | tr a-z A-Z`
93 fi
94 else
95 echo "$self: Fatal: \"$1\" option requires parameter." >&2
96 exit 1
97 fi
98 ;;
99 -q|--quiet)
100 quiet=:
101 ;;
102 -h|--help)
103 echo "Usage: ${self} $USAGE"
104 [ -n "$LONG_USAGE" ] && echo "$LONG_USAGE"
105 exit
106 ;;
107 -k|--keep-if-no-repo)
108 keep_if_no_repo=yes
109 ;;
110 -s|--srcdir)
111 if shift; then
112 if test -d "$1"; then
113 srcdir="$1"
114 else
115 echo "$self: Fatal: \"$1\" not a directory." >&2
116 exit 1
117 fi
118 else
119 echo "$self: Fatal: \"$1\" option requires directory parameter." >&2
120 exit 1
121 fi
122 ;;
123 *)
124 echo "$self: Fatal: Invalid command line paramenter: \"$1\"" >&2
125 exit 1
126 ;;
127 esac
128 shift
129done
130
2899dcf6 131# If not printing to stdout, redirect stdout to output file?
c0f9d4b0
FCE
132rename_new_output=false
133if [ "x$outfile" = "x-" ]
134then
135 : # keep using stdout
136else
2899dcf6 137 exec 1> "${outfile}.new"
c0f9d4b0
FCE
138fi
139
140# Done with creating output files, so we can change to source dir
2899dcf6 141abs_srcdir=`cd "$srcdir" && pwd`
c0f9d4b0
FCE
142cd "$srcdir"
143
144# Write program header
145cat<<EOF
146/*
147 * Basic versioning gathered from the git repository.
148 * Automatically generated by $0.
149 */
150
151#ifndef ${ifndef_symbol}
152#define ${ifndef_symbol} 1
153
2899dcf6
FCE
154#include <stdint.h>
155
c0f9d4b0
FCE
156/* whether this is a dist tarball or not */
157#undef GIT_IS_DIST
158
159EOF
160
2899dcf6 161# Detect git tool (should work with old and new git versions)
f66e74de
FCE
162if type $GIT >/dev/null 2>&1; then
163 git_found=yes
164else
165 git_found="'$GIT' not found"
2899dcf6
FCE
166fi
167# If git_found=yes, we can now use $() substitutions (as git does). Hooray!
c0f9d4b0
FCE
168
169# Determine git specific defines
170unset git_errors ||:
171if [ "x$git_found" = "xyes" ]; then
2899dcf6 172 git_version=`$GIT --version`
c0f9d4b0 173 if [ "x$git_version" = "x" ]; then
2899dcf6 174 git_errors="${git_errors+${git_errors}; }error running '$GIT --version'"
c0f9d4b0
FCE
175 fi
176fi
177
178git_repo=no
179# "git-rev-parse --git-dir" since git-0.99.7
2899dcf6 180git_repo_dir="$($GIT rev-parse --git-dir 2> /dev/null || true)"
c0f9d4b0 181abs_repo_dir="$(cd "$git_repo_dir" && pwd)"
a73db1bd
FCE
182# Don't be so picky as to only accept the found git repo iff it is in
183# our top srcdir, as determined by comparing absolute pathnames
184# created by running pwd in the respective dir. That is incompatible
185# with "git worktree" instances.
186if [ "x$git_repo_dir" != "x" ]; then #
c0f9d4b0
FCE
187 git_repo=yes
188 if [ "x$git_found" = "xyes" ]; then
189 # git-1.4 and probably earlier understand "git-rev-parse HEAD"
2899dcf6 190 git_shaid=`$GIT rev-parse HEAD`
c0f9d4b0 191 if [ "x$git_shaid" = "x" ]; then
2899dcf6
FCE
192 git_errors="${git_errors+${git_errors}; }error running '$GIT rev-parse HEAD'"
193 fi
194 git_shaid_short=`$GIT rev-parse HEAD | $SED -n 's/^\(.\{8\}\).*/\1/p'`
195 if [ "x$git_shaid_short" = "x" ]; then
196 git_errors="${git_errors+${git_errors}; }error running '$GIT rev-parse HEAD'"
c0f9d4b0
FCE
197 fi
198 # git-1.4 and probably earlier understand "git-symbolic-ref HEAD"
2899dcf6 199 git_branch=`$GIT symbolic-ref HEAD | $SED -n 's|^refs/heads/||p'`
c0f9d4b0
FCE
200 if [ "x$git_branch" = "x" ]; then
201 # This happens, is OK, and "(no branch)" is what "git branch" prints.
202 git_branch="(no branch)"
203 fi
204 git_dirty=yes
205 # git-1.4 does not understand "git-diff-files --quiet"
206 # git-1.4 does not understand "git-diff-index --cached --quiet HEAD"
2899dcf6 207 if [ "x$($GIT diff-files)" = "x" ] && [ "x$($GIT diff-index --cached HEAD)" = "x" ]; then
c0f9d4b0
FCE
208 git_dirty=no
209 fi
2899dcf6
FCE
210 # Grab the origin url, stripping out any credentials that might be in it
211 git_remote_url=`$GIT config --get remote.origin.url | $SED -nE 's/^(.*:\/\/)(.*\@)?(.*)$/\3/p'`
212 if [ "x$git_remote_url" = "x" ]; then
213 git_remote_url="(no remote)"
214 fi
215 # Grab the linear git revision number
216 git_build=`$GIT log --oneline | wc -l | $SED 's/^[ \t]*//'`
4c6771bd 217 if [ "x$git_build" = "x" ]; then
2899dcf6
FCE
218 git_errors="${git_errors+${git_errors}; }error running '$GIT log --oneline'"
219 fi
220 # Grab the "pretty" revision number
f06461a9 221 git_pretty_rev=`$GIT describe --dirty --always --abbrev=8`
4c6771bd 222 if [ "x$git_pretty_rev" = "x" ]; then
2899dcf6
FCE
223 git_errors="${git_errors+${git_errors}; }error running '$GIT describe'"
224 fi
225 # Grab the commit timestamp
6b17715f 226 git_timestamp=`$GIT show -s --format=%ct | tail -1`
2899dcf6
FCE
227 if [ "x$git_timestamp" = "x" ]; then
228 git_errors="${git_errors+${git_errors}; }error running '$GIT show -s --format=%ct'"
229 fi
c0f9d4b0
FCE
230 fi
231fi
232
233# Write git specific defines
234if [ "x$git_errors" = "x" ]; then
235 echo "/* No errors occured while running git */"
236 echo "#undef GIT_ERRORS"
237else
238 echo "/* Some errors occured while running git */"
239 echo "#define GIT_ERRORS \"${git_errors}\""
240fi
241echo ""
242
243if [ "x$git_found" = "xyes" ]; then
244 echo "/* git utilities found */"
245 echo "#undef GIT_NOT_FOUND"
246 echo "#define GIT_VERSION \"${git_version}\""
247else
248 echo "/* git utilities not found */"
249 echo "#define GIT_NOT_FOUND \"${git_found}\""
250 echo "#undef GIT_VERSION"
251fi
252echo ""
253
2899dcf6
FCE
254if :; then # debug output
255cat<<EOF
256/* The following helps debug why we sometimes do not find ".git/":
257 * abs_repo_dir="${abs_repo_dir}" (should be "/path/to/.git")
258 * abs_srcdir="${abs_srcdir}" (absolute top source dir "/path/to")
259 * git_repo_dir="${git_repo_dir}" (usually ".git" or "/path/to/.git")
260 * PWD="${PWD}"
261 * srcdir="${srcdir}"
262 * working_dir="${working_dir}"
263 */
264
265EOF
266fi
267
c0f9d4b0
FCE
268if [ "x$git_repo" = "xno" ]; then
269 echo "/* No git repo found, probably building from dist tarball */"
270 echo "#undef GIT_REPO"
271else
272 echo "/* git repo found */"
273 echo "#define GIT_REPO 1"
274 echo ""
275 if [ "x$git_found" = "xyes" ]; then
2899dcf6 276 echo "/* Full git SHA ID of last commit */"
c0f9d4b0
FCE
277 echo "#define GIT_SHAID \"${git_shaid}\""
278 echo ""
279
2899dcf6
FCE
280 echo "/* Short form of the above */"
281 echo "#define GIT_SHAID_SHORT \"${git_shaid_short}\""
282 echo ""
283
c0f9d4b0
FCE
284 echo "/* Branch this tree is on */"
285 echo "#define GIT_BRANCH \"$git_branch\""
286 echo ""
287
2899dcf6
FCE
288 echo "/* Remote URL this tree was cloned from */"
289 echo "#define GIT_REMOTE_URL \"$git_remote_url\""
290 echo ""
291
292 echo "/* Linear revision number from the repository */"
293 echo "#define GIT_BUILD \"$git_build\""
294 echo ""
295
296 echo "/* Pretty git revision string for presenting to the user */"
297 echo "#define GIT_PRETTY_REV \"$git_pretty_rev\""
298 echo ""
299
300 echo "/* Timestamp of the current commit */"
301 echo "#define GIT_TIMESTAMP UINT64_C($git_timestamp)"
302 echo ""
303
c0f9d4b0
FCE
304 # Any uncommitted changes we should know about?
305 # Or technically: Are the working tree or index dirty?
306 if [ "x$git_dirty" = "xno" ]; then
307 echo "/* SHA-ID uniquely defines the state of this code */"
308 echo "#undef GIT_DIRTY"
309 else
310 echo "/* Local changes might be breaking things */"
311 echo "#define GIT_DIRTY 1"
312 fi
313 fi
314fi
315
316# Define a few immediately useful message strings
317cat<<EOF
318
319/* Define GIT_MESSAGE such that
320 * printf("%s: built from %s", argv[0], GIT_MESSAGE);
321 * forms a proper sentence.
322 */
323
324#ifdef GIT_DIRTY
2899dcf6 325# define GIT_DIRTY_MSG "-dirty"
c0f9d4b0
FCE
326#else /* !GIT_DIRTY */
327# define GIT_DIRTY_MSG ""
328#endif /* GIT_DIRTY */
329
330#ifdef GIT_ERRORS
331# define GIT_ERROR_MSG " with error: " GIT_ERRORS
332#else /* !GIT_ERRORS */
333# define GIT_ERROR_MSG ""
334#endif /* GIT_ERRORS */
335
336#ifdef GIT_IS_DIST
337# define GIT_DIST_MSG "dist of "
338#else /* !GIT_IS_DIST */
339# define GIT_DIST_MSG ""
340#endif /* GIT_IS_DIST */
341
342#ifdef GIT_REPO
343# ifdef GIT_NOT_FOUND
344# define GIT_MESSAGE GIT_DIST_MSG "git sources without git: " GIT_NOT_FOUND
345# else /* !GIT_NOT_FOUND */
346# define GIT_MESSAGE \\
347 GIT_DIST_MSG \\
2899dcf6
FCE
348 "git branch " GIT_BRANCH ", " \\
349 "url " GIT_REMOTE_URL ", " \\
c0f9d4b0
FCE
350 "commit " GIT_SHAID GIT_DIRTY_MSG \\
351 GIT_ERROR_MSG
352# endif /* GIT_NOT_FOUND */
353#else /* !GIT_REPO */
354# define GIT_MESSAGE GIT_DIST_MSG "non-git sources" GIT_ERROR_MSG
355#endif /* GIT_REPO */
356
357#endif /* ${ifndef_symbol} */
358EOF
359
360# Example program
361if "$print_example"
362then
363 cat<<EOF
364
365/* example program demonstrating the use of git_version.sh output */
366#include <stdio.h>
367#include <string.h>
368
369#ifdef HAVE_CONFIG_H
370# include "config.h"
371#endif
372
373int main(int argc, char *argv[])
374{
375 const char *const idx = strrchr(argv[0], '/');
376 const char *const prog = (idx)?(idx+1):(argv[0]);
377#ifdef PACKAGE_VERSION
378 printf("%s: version %s, built from %s\n", prog, PACKAGE_VERSION, GIT_MESSAGE);
23957b6c 379#elif defined(GIT_MESSAGE)
c0f9d4b0
FCE
380 printf("%s: built from %s\n", prog, GIT_MESSAGE);
381#endif
382 return 0;
383}
384EOF
385fi
386
387# Change back to working dir for the remaining output file manipulations.
388cd "$working_dir"
389
390# If necessary, overwrite outdated output file with new one
391if [ "x$outfile" != "x-" ]
392then
393 if [ -f "$outfile" ]; then
394 if [ "x$keep_if_no_repo" = "xyes" ] && [ "x$git_repo" = "xno" ]; then
395 "$quiet" || echo "$self: Not a git repo, keeping existing $outfile" >&2
2899dcf6
FCE
396 rm -f "$outfile.new"
397 elif cmp "$outfile" "$outfile.new" > /dev/null; then
c0f9d4b0 398 "$quiet" || echo "$self: Output is unchanged, keeping $outfile" >&2
2899dcf6 399 rm -f "$outfile.new"
c0f9d4b0
FCE
400 else
401 echo "$self: Output has changed, updating $outfile" >&2
2899dcf6 402 mv -f "$outfile.new" "$outfile"
c0f9d4b0
FCE
403 fi
404 else
405 echo "$self: Output is new file, creating $outfile" >&2
2899dcf6 406 mv -f "$outfile.new" "$outfile"
c0f9d4b0
FCE
407 fi
408fi
409
410# THE END.
This page took 0.192691 seconds and 6 git commands to generate.