#!/bin/sh # Generate some basic info on source code version to be included in program. # # Copyright (c) 2006-2007 Luc Verhaegen # Copyright (C) 2007 Hans Ulrich Niedermann # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # # The author thanks the nice people on #git for the assistance! # # Simple testing of this script: # env SED="/sbin/busybox sed" \ # /sbin/busybox sh git-buildmsg --example > moo.c \ # && gcc -Wall -Wextra -Wno-unused -o moo moo.c \ # && ./moo # (bash and other seds should also do) # # Ideas: # * Output for languages other than C (Erlang, Python, Perl, sh, ...) # The caller may have found these programs for us SED="${SED-sed}" # Initialize GIT_DIR=".git" working_dir="$(pwd)" # Who am I? self="$(basename "$0")" # Defaults ifndef_symbol="GIT_VERSION_H" outfile="-" print_example=false srcdir="$(pwd)" # Parse command line parameter, affecting defaults while [ "x$1" != "x" ] do case "$1" in --example) print_example=: ;; -o|--output) if shift; then outfile="$1" if [ "x$outfile" = "x-" ]; then : # keep default ifndef_symbol else ifndef_symbol=`basename "$outfile" | $SED 's|\.|_|g; s|[^A-Za-z0-9_]||g' | tr a-z A-Z` fi else echo "$self: Fatal: \"$1\" option requires parameter." >&2 exit 1 fi ;; --version) echo "$self (@PACKAGE_NAME@) @PACKAGE_VERSION@" exit ;; --help) echo "Supported params: --help, --example, -o|--output" exit ;; -s|--srcdir) if shift; then if test -d "$1"; then srcdir="$1" else echo "$self: Fatal: \"$1\" not a directory." exit 1 fi else echo "$self: Fatal: \"$1\" option requires directory parameter." exit 1 fi ;; *) echo "$self: Fatal: Invalid command line paramenter: \"$1\"" >&2 exit 1 ;; esac shift done # If not printing to stdout, redirect stdout to output file rename_new_output=false if [ "x$outfile" = "x-" ] then : # keep using stdout else exec 1> "${outfile}.new" fi # Done with creating output files, so we can change to source dir cd "$srcdir" # Write program header cat</dev/null` = "x" ] && { git_found=no; break; } done # Determine and write git specific defines if [ "x$git_found" = "xyes" ]; then if [ -e "$GIT_DIR/index" ]; then echo "/* This is a git repository */" echo "#define GIT_USED 1" echo "" # Commit SHA-ID git_shaid=`git-rev-parse HEAD | $SED -n 's/^\(.\{8\}\).*/\1/p'` echo "/* Git SHA ID of last commit */" echo "#define GIT_SHAID \"${git_shaid}..\"" echo "" # Branch git_branch=`git-symbolic-ref HEAD | $SED -n 's|^refs/heads/||p'` echo "/* Branch this tree is on */" echo "#define GIT_BRANCH \"$git_branch\"" echo "" # Any uncommitted changes we should know about? # Or technically: Are the working tree or index dirty? if git-diff-files --quiet && git-diff-index --cached --quiet HEAD; then echo "/* SHA-ID uniquely defines the state of this code */" echo "#undef GIT_UNCOMMITTED" else echo "/* Local changes might be breaking things */" echo "#define GIT_UNCOMMITTED 1" fi else echo "/* This is not a git repository */" echo "#undef GIT_USED" fi else echo "/* git is not installed */" echo "#undef GIT_USED" fi # Define a few immediately useful message strings cat< #include int main(int argc, char *argv[]) { const char *const idx = strrchr(argv[0], '/'); const char *const prog = (idx)?(idx+1):(argv[0]); #ifdef PACKAGE_VERSION printf("%s: version %s, built from %s\n", prog, PACKAGE_VERSION, GIT_MESSAGE); #elif defined(GIT_USED) printf("%s: built from %s\n", prog, GIT_MESSAGE); #endif return 0; } EOF fi # Change back to working dir for the remaining output file manipulations. cd "$working_dir" # If necessary, overwrite outdated output file with new one if [ "x$outfile" != "x-" ] then if [ -f "$outfile" ]; then if cmp "$outfile" "$outfile.new" > /dev/null; then echo "$self: Output is unchanged, keeping $outfile" >&2 rm -f "$outfile.new" else echo "$self: Output has changed, updating $outfile" >&2 mv -f "$outfile.new" "$outfile" fi else mv -f "$outfile.new" "$outfile" fi fi # THE END.