]>
Commit | Line | Data |
---|---|---|
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> | |
6 | # Copyright (C) 2007 Hans Ulrich Niedermann <hun@n-dimensional.de> | |
7 | # | |
8 | # Permission is hereby granted, free of charge, to any person obtaining a | |
9 | # copy of this software and associated documentation files (the "Software"), | |
10 | # to deal in the Software without restriction, including without limitation | |
11 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
12 | # and/or sell copies of the Software, and to permit persons to whom the | |
13 | # Software is furnished to do so, subject to the following conditions: | |
14 | # | |
15 | # The above copyright notice and this permission notice shall be included in | |
16 | # all copies or substantial portions of the Software. | |
17 | # | |
18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
21 | # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
22 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
23 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
24 | # OTHER DEALINGS IN THE SOFTWARE. | |
25 | # | |
26 | # This script is based on the one written for xf86-video-unichrome by | |
27 | # Luc Verhaegen, but was rewritten almost completely by Hans Ulrich | |
28 | # Niedermann. The script contains a few bug fixes from Egbert Eich, | |
29 | # Matthias Hopf, Joerg Sonnenberger, and possibly others. | |
30 | # | |
31 | # The author thanks the nice people on #git for the assistance. | |
32 | # | |
33 | # Simple testing of this script: | |
34 | # /sbin/busybox sh git_version.sh --example > moo.c \ | |
35 | # && gcc -Wall -Wextra -Wno-unused -o moo moo.c \ | |
36 | # && ./moo | |
37 | # (bash should also do) | |
38 | # | |
39 | # For how to hook this up to your automake- and/or imake-based build | |
40 | # system, best take a look at how the RadeonHD.am and/or RadeonHD.tmpl | |
41 | # work in the xf86-video-radeonhd build system. For non-recursive make, | |
42 | # you can probably make things a little bit simpler. | |
43 | # | |
44 | # KNOWN BUGS: | |
45 | # * Uses hyphenated ("git-foo-bar") program names, which git upstream | |
46 | # have declared deprecated. | |
47 | # | |
48 | ||
49 | # Help messages | |
50 | USAGE="[<option>...]" | |
51 | LONG_USAGE="\ | |
52 | Options: | |
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 | |
62 | SED="${SED-sed}" | |
63 | ||
64 | # Initialize | |
65 | working_dir="$(pwd)" | |
66 | ||
67 | # Who am I? | |
68 | self="$(basename "$0")" | |
69 | ||
70 | # Defaults | |
71 | ifndef_symbol="GIT_VERSION_H" | |
72 | outfile="-" | |
73 | print_example=false | |
74 | keep_if_no_repo=no | |
75 | quiet=false | |
76 | srcdir="$(pwd)" | |
77 | ||
78 | # Parse command line parameter, affecting defaults | |
79 | while [ "x$1" != "x" ] | |
80 | do | |
81 | case "$1" in | |
82 | -x|--example) | |
83 | print_example=: | |
84 | ;; | |
85 | -o|--output) | |
86 | if shift; then | |
87 | outfile="$1" | |
88 | if [ "x$outfile" = "x-" ]; then | |
89 | : # keep default ifndef_symbol | |
90 | else | |
7020ae00 MW |
91 | newdir=$(mktemp -t -d git_version_XXXXXX) |
92 | outfilenew="$newdir/$1.new" | |
c0f9d4b0 FCE |
93 | ifndef_symbol=`basename "$outfile" | $SED 's|\.|_|g; s|[^A-Za-z0-9_]||g' | tr a-z A-Z` |
94 | fi | |
95 | else | |
96 | echo "$self: Fatal: \"$1\" option requires parameter." >&2 | |
97 | exit 1 | |
98 | fi | |
99 | ;; | |
100 | -q|--quiet) | |
101 | quiet=: | |
102 | ;; | |
103 | -h|--help) | |
104 | echo "Usage: ${self} $USAGE" | |
105 | [ -n "$LONG_USAGE" ] && echo "$LONG_USAGE" | |
106 | exit | |
107 | ;; | |
108 | -k|--keep-if-no-repo) | |
109 | keep_if_no_repo=yes | |
110 | ;; | |
111 | -s|--srcdir) | |
112 | if shift; then | |
113 | if test -d "$1"; then | |
114 | srcdir="$1" | |
115 | else | |
116 | echo "$self: Fatal: \"$1\" not a directory." >&2 | |
117 | exit 1 | |
118 | fi | |
119 | else | |
120 | echo "$self: Fatal: \"$1\" option requires directory parameter." >&2 | |
121 | exit 1 | |
122 | fi | |
123 | ;; | |
124 | *) | |
125 | echo "$self: Fatal: Invalid command line paramenter: \"$1\"" >&2 | |
126 | exit 1 | |
127 | ;; | |
128 | esac | |
129 | shift | |
130 | done | |
131 | ||
132 | # If not printing to stdout, redirect stdout to output file | |
133 | rename_new_output=false | |
134 | if [ "x$outfile" = "x-" ] | |
135 | then | |
136 | : # keep using stdout | |
137 | else | |
7020ae00 | 138 | exec 1> "${outfilenew}" |
c0f9d4b0 FCE |
139 | fi |
140 | ||
141 | # Done with creating output files, so we can change to source dir | |
142 | abs_srcdir="$(cd "$srcdir" && pwd)" | |
143 | cd "$srcdir" | |
144 | ||
145 | # Write program header | |
146 | cat<<EOF | |
147 | /* | |
148 | * Basic versioning gathered from the git repository. | |
149 | * Automatically generated by $0. | |
150 | */ | |
151 | ||
152 | #ifndef ${ifndef_symbol} | |
153 | #define ${ifndef_symbol} 1 | |
154 | ||
155 | /* whether this is a dist tarball or not */ | |
156 | #undef GIT_IS_DIST | |
157 | ||
158 | EOF | |
159 | ||
d99a656a TT |
160 | # Backwards compatibility hack for git 1.6.0 (and people running the |
161 | # latest pre-release version of git.) | |
162 | # | |
163 | # For now, we'll do this to support git 1.6, with minimal changes to | |
164 | # the rest of this script, but no guarantees how long this will work. | |
165 | # The hyphenated git-foo-bar names really are deprecated, and may | |
166 | # disappear in the future as more of git gets rewritten as built-in C | |
167 | # programs. Google summer of code students and other git developers | |
168 | # are hard at work doing this, in order to make git more | |
169 | # portable/usable for Windows users. As a result, some of the | |
170 | # git-foo-bar programs, which will be moved to the exec-dir directory | |
171 | # in git 1.6, may disappear altogether in the future. Hence the only | |
172 | # truly safe and future-compatible way of running commands such as | |
173 | # git-diff-files, git-rev-parse, etc., are "git diff-files" and | |
174 | # "git rev-parse". Here endeth the git portability sermon, which | |
175 | # I suspect will have as much effect as abstinence-only sex ed | |
176 | # classes. :-) TYT, 2008-07-08 | |
177 | ||
178 | execdir=$(git --exec-path 2> /dev/null) | |
179 | if test -n "$execdir"; then | |
180 | PATH=$PATH:$execdir | |
181 | fi | |
182 | ||
c0f9d4b0 FCE |
183 | # Detect git tools (should work with old and new git versions) |
184 | git_found=yes | |
c0dac698 | 185 | for git_tool in git-symbolic-ref git-rev-parse git-diff-files git-diff-index git git-describe |
c0f9d4b0 FCE |
186 | do |
187 | if [ x`which $git_tool 2>/dev/null` = "x" ]; then | |
188 | git_found="'$git_tool' not found" | |
189 | break | |
190 | fi | |
191 | done | |
192 | ||
193 | # Determine git specific defines | |
194 | unset git_errors ||: | |
195 | if [ "x$git_found" = "xyes" ]; then | |
196 | git_version=`git --version` | |
197 | if [ "x$git_version" = "x" ]; then | |
198 | git_errors="${git_errors+${git_errors}; }error running 'git --version'" | |
199 | fi | |
200 | fi | |
201 | ||
202 | git_repo=no | |
203 | # "git-rev-parse --git-dir" since git-0.99.7 | |
204 | git_repo_dir="$(git-rev-parse --git-dir 2> /dev/null || true)" | |
205 | abs_repo_dir="$(cd "$git_repo_dir" && pwd)" | |
206 | # Only accept the found git repo iff it is in our top srcdir, as determined | |
207 | # by comparing absolute pathnames creaged by running pwd in the respective dir. | |
208 | if [ "x$git_repo_dir" != "x" ] && [ "x${abs_repo_dir}" = "x${abs_srcdir}/.git" ]; then | |
209 | git_repo=yes | |
210 | if [ "x$git_found" = "xyes" ]; then | |
211 | # git-1.4 and probably earlier understand "git-rev-parse HEAD" | |
c08d4d26 JS |
212 | git_shaid=`git-describe --abbrev=12 --long 2>/dev/null || |
213 | git-describe --abbrev=12 2>/dev/null || | |
214 | git-rev-parse HEAD` | |
c0f9d4b0 FCE |
215 | if [ "x$git_shaid" = "x" ]; then |
216 | git_errors="${git_errors+${git_errors}; }error running 'git-rev-parse HEAD'" | |
217 | fi | |
218 | # git-1.4 and probably earlier understand "git-symbolic-ref HEAD" | |
219 | git_branch=`git-symbolic-ref HEAD | $SED -n 's|^refs/heads/||p'` | |
220 | if [ "x$git_branch" = "x" ]; then | |
221 | # This happens, is OK, and "(no branch)" is what "git branch" prints. | |
222 | git_branch="(no branch)" | |
223 | fi | |
224 | git_dirty=yes | |
225 | # git-1.4 does not understand "git-diff-files --quiet" | |
226 | # git-1.4 does not understand "git-diff-index --cached --quiet HEAD" | |
39842e90 | 227 | if [ "x$(git-diff-files)" = "x" ] && [ "x$(git-diff-index --cached HEAD)" = "x" ]; then |
c0f9d4b0 FCE |
228 | git_dirty=no |
229 | fi | |
230 | fi | |
231 | fi | |
232 | ||
233 | # Write git specific defines | |
234 | if [ "x$git_errors" = "x" ]; then | |
235 | echo "/* No errors occured while running git */" | |
236 | echo "#undef GIT_ERRORS" | |
237 | else | |
238 | echo "/* Some errors occured while running git */" | |
239 | echo "#define GIT_ERRORS \"${git_errors}\"" | |
240 | fi | |
241 | echo "" | |
242 | ||
243 | if [ "x$git_found" = "xyes" ]; then | |
244 | echo "/* git utilities found */" | |
245 | echo "#undef GIT_NOT_FOUND" | |
246 | echo "#define GIT_VERSION \"${git_version}\"" | |
247 | else | |
248 | echo "/* git utilities not found */" | |
249 | echo "#define GIT_NOT_FOUND \"${git_found}\"" | |
250 | echo "#undef GIT_VERSION" | |
251 | fi | |
252 | echo "" | |
253 | ||
254 | if [ "x$git_repo" = "xno" ]; then | |
255 | echo "/* No git repo found, probably building from dist tarball */" | |
256 | echo "#undef GIT_REPO" | |
257 | else | |
258 | echo "/* git repo found */" | |
259 | echo "#define GIT_REPO 1" | |
260 | echo "" | |
261 | if [ "x$git_found" = "xyes" ]; then | |
262 | echo "/* Git SHA ID of last commit */" | |
263 | echo "#define GIT_SHAID \"${git_shaid}\"" | |
264 | echo "" | |
265 | ||
266 | echo "/* Branch this tree is on */" | |
267 | echo "#define GIT_BRANCH \"$git_branch\"" | |
268 | echo "" | |
269 | ||
270 | # Any uncommitted changes we should know about? | |
271 | # Or technically: Are the working tree or index dirty? | |
272 | if [ "x$git_dirty" = "xno" ]; then | |
273 | echo "/* SHA-ID uniquely defines the state of this code */" | |
274 | echo "#undef GIT_DIRTY" | |
275 | else | |
276 | echo "/* Local changes might be breaking things */" | |
277 | echo "#define GIT_DIRTY 1" | |
278 | fi | |
279 | fi | |
280 | fi | |
281 | ||
282 | # Define a few immediately useful message strings | |
283 | cat<<EOF | |
284 | ||
285 | /* Define GIT_MESSAGE such that | |
286 | * printf("%s: built from %s", argv[0], GIT_MESSAGE); | |
287 | * forms a proper sentence. | |
288 | */ | |
289 | ||
290 | #ifdef GIT_DIRTY | |
291 | # define GIT_DIRTY_MSG " + changes" | |
292 | #else /* !GIT_DIRTY */ | |
293 | # define GIT_DIRTY_MSG "" | |
294 | #endif /* GIT_DIRTY */ | |
295 | ||
296 | #ifdef GIT_ERRORS | |
297 | # define GIT_ERROR_MSG " with error: " GIT_ERRORS | |
298 | #else /* !GIT_ERRORS */ | |
299 | # define GIT_ERROR_MSG "" | |
300 | #endif /* GIT_ERRORS */ | |
301 | ||
302 | #ifdef GIT_IS_DIST | |
303 | # define GIT_DIST_MSG "dist of " | |
304 | #else /* !GIT_IS_DIST */ | |
305 | # define GIT_DIST_MSG "" | |
306 | #endif /* GIT_IS_DIST */ | |
307 | ||
308 | #ifdef GIT_REPO | |
309 | # ifdef GIT_NOT_FOUND | |
310 | # define GIT_MESSAGE GIT_DIST_MSG "git sources without git: " GIT_NOT_FOUND | |
311 | # else /* !GIT_NOT_FOUND */ | |
312 | # define GIT_MESSAGE \\ | |
313 | GIT_DIST_MSG \\ | |
c0f9d4b0 FCE |
314 | "commit " GIT_SHAID GIT_DIRTY_MSG \\ |
315 | GIT_ERROR_MSG | |
316 | # endif /* GIT_NOT_FOUND */ | |
317 | #else /* !GIT_REPO */ | |
318 | # define GIT_MESSAGE GIT_DIST_MSG "non-git sources" GIT_ERROR_MSG | |
319 | #endif /* GIT_REPO */ | |
320 | ||
321 | #endif /* ${ifndef_symbol} */ | |
322 | EOF | |
323 | ||
324 | # Example program | |
325 | if "$print_example" | |
326 | then | |
327 | cat<<EOF | |
328 | ||
329 | /* example program demonstrating the use of git_version.sh output */ | |
330 | #include <stdio.h> | |
331 | #include <string.h> | |
332 | ||
333 | #ifdef HAVE_CONFIG_H | |
334 | # include "config.h" | |
335 | #endif | |
336 | ||
337 | int main(int argc, char *argv[]) | |
338 | { | |
339 | const char *const idx = strrchr(argv[0], '/'); | |
340 | const char *const prog = (idx)?(idx+1):(argv[0]); | |
341 | #ifdef PACKAGE_VERSION | |
342 | printf("%s: version %s, built from %s\n", prog, PACKAGE_VERSION, GIT_MESSAGE); | |
23957b6c | 343 | #elif defined(GIT_MESSAGE) |
c0f9d4b0 FCE |
344 | printf("%s: built from %s\n", prog, GIT_MESSAGE); |
345 | #endif | |
346 | return 0; | |
347 | } | |
348 | EOF | |
349 | fi | |
350 | ||
351 | # Change back to working dir for the remaining output file manipulations. | |
352 | cd "$working_dir" | |
353 | ||
354 | # If necessary, overwrite outdated output file with new one | |
355 | if [ "x$outfile" != "x-" ] | |
356 | then | |
357 | if [ -f "$outfile" ]; then | |
358 | if [ "x$keep_if_no_repo" = "xyes" ] && [ "x$git_repo" = "xno" ]; then | |
359 | "$quiet" || echo "$self: Not a git repo, keeping existing $outfile" >&2 | |
7020ae00 MW |
360 | rm -f "$outfilenew" |
361 | elif cmp "$outfile" "$outfilenew" > /dev/null; then | |
c0f9d4b0 | 362 | "$quiet" || echo "$self: Output is unchanged, keeping $outfile" >&2 |
7020ae00 | 363 | rm -f "$outfilenew" |
c0f9d4b0 FCE |
364 | else |
365 | echo "$self: Output has changed, updating $outfile" >&2 | |
7020ae00 | 366 | mv -f "$outfilenew" "$outfile" |
c0f9d4b0 FCE |
367 | fi |
368 | else | |
369 | echo "$self: Output is new file, creating $outfile" >&2 | |
7020ae00 | 370 | mv -f "$outfilenew" "$outfile" |
c0f9d4b0 | 371 | fi |
7020ae00 | 372 | rmdir "$newdir" |
c0f9d4b0 FCE |
373 | fi |
374 | ||
375 | # THE END. |