]>
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" | |
38e25872 | 212 | git_shaid=`git-describe --long 2>/dev/null || git-describe 2>/dev/null || git-rev-parse HEAD` |
c0f9d4b0 FCE |
213 | if [ "x$git_shaid" = "x" ]; then |
214 | git_errors="${git_errors+${git_errors}; }error running 'git-rev-parse HEAD'" | |
215 | fi | |
216 | # git-1.4 and probably earlier understand "git-symbolic-ref HEAD" | |
217 | git_branch=`git-symbolic-ref HEAD | $SED -n 's|^refs/heads/||p'` | |
218 | if [ "x$git_branch" = "x" ]; then | |
219 | # This happens, is OK, and "(no branch)" is what "git branch" prints. | |
220 | git_branch="(no branch)" | |
221 | fi | |
222 | git_dirty=yes | |
223 | # git-1.4 does not understand "git-diff-files --quiet" | |
224 | # git-1.4 does not understand "git-diff-index --cached --quiet HEAD" | |
39842e90 | 225 | if [ "x$(git-diff-files)" = "x" ] && [ "x$(git-diff-index --cached HEAD)" = "x" ]; then |
c0f9d4b0 FCE |
226 | git_dirty=no |
227 | fi | |
228 | fi | |
229 | fi | |
230 | ||
231 | # Write git specific defines | |
232 | if [ "x$git_errors" = "x" ]; then | |
233 | echo "/* No errors occured while running git */" | |
234 | echo "#undef GIT_ERRORS" | |
235 | else | |
236 | echo "/* Some errors occured while running git */" | |
237 | echo "#define GIT_ERRORS \"${git_errors}\"" | |
238 | fi | |
239 | echo "" | |
240 | ||
241 | if [ "x$git_found" = "xyes" ]; then | |
242 | echo "/* git utilities found */" | |
243 | echo "#undef GIT_NOT_FOUND" | |
244 | echo "#define GIT_VERSION \"${git_version}\"" | |
245 | else | |
246 | echo "/* git utilities not found */" | |
247 | echo "#define GIT_NOT_FOUND \"${git_found}\"" | |
248 | echo "#undef GIT_VERSION" | |
249 | fi | |
250 | echo "" | |
251 | ||
252 | if [ "x$git_repo" = "xno" ]; then | |
253 | echo "/* No git repo found, probably building from dist tarball */" | |
254 | echo "#undef GIT_REPO" | |
255 | else | |
256 | echo "/* git repo found */" | |
257 | echo "#define GIT_REPO 1" | |
258 | echo "" | |
259 | if [ "x$git_found" = "xyes" ]; then | |
260 | echo "/* Git SHA ID of last commit */" | |
261 | echo "#define GIT_SHAID \"${git_shaid}\"" | |
262 | echo "" | |
263 | ||
264 | echo "/* Branch this tree is on */" | |
265 | echo "#define GIT_BRANCH \"$git_branch\"" | |
266 | echo "" | |
267 | ||
268 | # Any uncommitted changes we should know about? | |
269 | # Or technically: Are the working tree or index dirty? | |
270 | if [ "x$git_dirty" = "xno" ]; then | |
271 | echo "/* SHA-ID uniquely defines the state of this code */" | |
272 | echo "#undef GIT_DIRTY" | |
273 | else | |
274 | echo "/* Local changes might be breaking things */" | |
275 | echo "#define GIT_DIRTY 1" | |
276 | fi | |
277 | fi | |
278 | fi | |
279 | ||
280 | # Define a few immediately useful message strings | |
281 | cat<<EOF | |
282 | ||
283 | /* Define GIT_MESSAGE such that | |
284 | * printf("%s: built from %s", argv[0], GIT_MESSAGE); | |
285 | * forms a proper sentence. | |
286 | */ | |
287 | ||
288 | #ifdef GIT_DIRTY | |
289 | # define GIT_DIRTY_MSG " + changes" | |
290 | #else /* !GIT_DIRTY */ | |
291 | # define GIT_DIRTY_MSG "" | |
292 | #endif /* GIT_DIRTY */ | |
293 | ||
294 | #ifdef GIT_ERRORS | |
295 | # define GIT_ERROR_MSG " with error: " GIT_ERRORS | |
296 | #else /* !GIT_ERRORS */ | |
297 | # define GIT_ERROR_MSG "" | |
298 | #endif /* GIT_ERRORS */ | |
299 | ||
300 | #ifdef GIT_IS_DIST | |
301 | # define GIT_DIST_MSG "dist of " | |
302 | #else /* !GIT_IS_DIST */ | |
303 | # define GIT_DIST_MSG "" | |
304 | #endif /* GIT_IS_DIST */ | |
305 | ||
306 | #ifdef GIT_REPO | |
307 | # ifdef GIT_NOT_FOUND | |
308 | # define GIT_MESSAGE GIT_DIST_MSG "git sources without git: " GIT_NOT_FOUND | |
309 | # else /* !GIT_NOT_FOUND */ | |
310 | # define GIT_MESSAGE \\ | |
311 | GIT_DIST_MSG \\ | |
c0f9d4b0 FCE |
312 | "commit " GIT_SHAID GIT_DIRTY_MSG \\ |
313 | GIT_ERROR_MSG | |
314 | # endif /* GIT_NOT_FOUND */ | |
315 | #else /* !GIT_REPO */ | |
316 | # define GIT_MESSAGE GIT_DIST_MSG "non-git sources" GIT_ERROR_MSG | |
317 | #endif /* GIT_REPO */ | |
318 | ||
319 | #endif /* ${ifndef_symbol} */ | |
320 | EOF | |
321 | ||
322 | # Example program | |
323 | if "$print_example" | |
324 | then | |
325 | cat<<EOF | |
326 | ||
327 | /* example program demonstrating the use of git_version.sh output */ | |
328 | #include <stdio.h> | |
329 | #include <string.h> | |
330 | ||
331 | #ifdef HAVE_CONFIG_H | |
332 | # include "config.h" | |
333 | #endif | |
334 | ||
335 | int main(int argc, char *argv[]) | |
336 | { | |
337 | const char *const idx = strrchr(argv[0], '/'); | |
338 | const char *const prog = (idx)?(idx+1):(argv[0]); | |
339 | #ifdef PACKAGE_VERSION | |
340 | printf("%s: version %s, built from %s\n", prog, PACKAGE_VERSION, GIT_MESSAGE); | |
23957b6c | 341 | #elif defined(GIT_MESSAGE) |
c0f9d4b0 FCE |
342 | printf("%s: built from %s\n", prog, GIT_MESSAGE); |
343 | #endif | |
344 | return 0; | |
345 | } | |
346 | EOF | |
347 | fi | |
348 | ||
349 | # Change back to working dir for the remaining output file manipulations. | |
350 | cd "$working_dir" | |
351 | ||
352 | # If necessary, overwrite outdated output file with new one | |
353 | if [ "x$outfile" != "x-" ] | |
354 | then | |
355 | if [ -f "$outfile" ]; then | |
356 | if [ "x$keep_if_no_repo" = "xyes" ] && [ "x$git_repo" = "xno" ]; then | |
357 | "$quiet" || echo "$self: Not a git repo, keeping existing $outfile" >&2 | |
7020ae00 MW |
358 | rm -f "$outfilenew" |
359 | elif cmp "$outfile" "$outfilenew" > /dev/null; then | |
c0f9d4b0 | 360 | "$quiet" || echo "$self: Output is unchanged, keeping $outfile" >&2 |
7020ae00 | 361 | rm -f "$outfilenew" |
c0f9d4b0 FCE |
362 | else |
363 | echo "$self: Output has changed, updating $outfile" >&2 | |
7020ae00 | 364 | mv -f "$outfilenew" "$outfile" |
c0f9d4b0 FCE |
365 | fi |
366 | else | |
367 | echo "$self: Output is new file, creating $outfile" >&2 | |
7020ae00 | 368 | mv -f "$outfilenew" "$outfile" |
c0f9d4b0 | 369 | fi |
7020ae00 | 370 | rmdir "$newdir" |
c0f9d4b0 FCE |
371 | fi |
372 | ||
373 | # THE END. |