3 # This script collates gcov data after one has configured with --enable-gcov,
4 # built, and run tests. It either outputs or POSTs to Coveralls a JSON text in
5 # the schema for the Coveralls API, which is documented here:
7 # https://docs.coveralls.io/api-introduction
8 # https://docs.coveralls.io/api-reference
10 # Currently only files in source languages supported by gcov(1) are reported
11 # on, though this can easily be extended. Currently that's only C/C++ files.
13 # This script is specifically written for Heimdal, which is an open source C
14 # codebases that uses autoconf and libtool for its build system. This means
15 # that sometimes the gcov notes and data files are not necessarily where the
16 # gcov(1) utility would find them, which is why this script exists instead of
17 # using some other integration script.
19 # Although this is specific to Heimdal, it can be extended.
21 # Note that one side effect of running this script, gcov(1) will be run for all
22 # C/C++ source files in the workspace. As well, some gcov notes and data files
23 # maybe hard-linked to other names. However, this script should be idempotent.
30 job
=${TRAVIS_JOB_ID:-}
39 token
=${COVERALLS_REPO_TOKEN:-}
44 ((${1:-1})) && exec 1>&2
46 Usage: $PROG [OPTIONS]
49 -q Quiet. Do not even emit warnings.
50 -v Verbose (on stderr). May be given multiple times.
51 -o - Output to stdout instead of POSTing to Coveralls.
52 -o FILE Output to FILE instead of POSTing to Coveralls.
53 -s CI-NAME Name of CI (e.g., "travis-ci")
54 Defaults to travis-ci.
55 -t TOKEN Token for Coveralls.
56 Defaults to \$COVERALLS_REPO_TOKEN.
57 -b BRANCH Name of branch the report is for.
58 Defaults to \$TRAVIS_BRANCH or currently-checked out branch in
60 -J ID Job ID (e.g., Travis-CI job ID)
61 Defaults to \${TRAVIS_JOB_ID}.
62 -i FILE Lists source files to run gcov(1) against
63 Defaults to \<(git ls-files -- '*.c' '*.cpp').
64 -S SRCDIR Path to workspace
66 -O OBJDIR Path to object directory if workspace is built out of tree
68 -U ORIGIN Name of origin.
69 Defaults to tracked upstream remote of BRANCH.
71 Defaults to git@github.com:\${TRAVIS_REPO_SLUG} or the push URI
72 for the ORIGIN remote of the workspace at SRCDIR.
74 $PROG will look for .gcno and .gcda files in OBJDIR for source files
75 in the workspace at SRCDIR and will run gcov on them, and produce
76 a request body as JSON in FILE (or stdout if -o FILE not given)
77 for the Coveralls API.
79 If -o FILE is not given, then $PROG will POST the JSON to Coveralls.
80 If -o FILE is given, then $PROG will not POST it to Coveralls.
82 If SRCDIR == OBJDIR == \$PWD, then -S and -O need not be given.
83 If running in a Travis-CI build, -J, -R, and -b need not be given, and -t
84 should not be given -- instead you should set a secret COVERALLS_REPO_TOKEN
85 environment variable in your project's Travis-CI's settings.
87 Only C and C++ source files are reported on. E.g., Yacc/Bison/Flex
88 source files are not reported.
90 The resulting JSON output is or can be POSTed to Coveralls with:
92 $ curl -sfg -X POST -F "json_file=@\${FILE}" -F "Filename=json_file" \\
93 https://coveralls.io/api/v1/jobs
98 while getopts +:J
:O
:R
:S
:U
:b
:hi
:o
:qs
:t
:vx opt
; do
101 O
) cd "$OPTARG"; objdir
=$PWD; cd "$OLDPWD";;
103 S
) cd "$OPTARG"; srcdir
=$PWD; cd "$OLDPWD";;
109 q
) quiet
=true
; verbose
=0;;
112 v
) quiet
=false
; ((verbose
++)) || true
; ((verbose
> 3)) && set -vx;;
117 # Note: we don't cd to $srcdir or $objdir or anywhere, so if $out is a relative
118 # path, we do the right thing.
120 : ${objdir:=${srcdir}}
121 : ${branch:=${TRAVIS_BRANCH:-$(cd "$srcdir" && git rev-parse --abbrev-ref HEAD)}}
123 if [[ -z ${origin:-} ]]; then
126 --format="%(refname:short) %(upstream:remotename)" refs
/heads |
128 [[ $gb = $branch ]] ||
continue
135 if [[ -z ${repo:-} ]]; then
136 if [[ -n ${TRAVIS_REPO_SLUG:-} ]]; then
137 repo
=git@github.com
:${TRAVIS_REPO_SLUG:-heimdal/heimdal}
139 repo
=$
(cd "$srcdir" && git remote get-url
--push "$origin")
143 if ((verbose
> 1)); then
151 [[ -n $d ]] && rm -rf "$d"
161 if [[ -n $flst ]]; then cat "$flst"; else git ls-files
-- '*.c' '*.cpp'; fi) |
163 # Remember to be careful to refer to ${srcdir}/${f}
164 ((verbose
)) && printf 'Processing: %s\n' "$f" 1>&2
170 if [[ ! -f ${objdir}/${dir}/.libs/${base}.gcda && ! -f ${objdir}/${dir}/${base}.gcda
]]; then
171 # Look for .libs/libfoo_la-${base}.gcda -- we don't know "foo", and
172 # there may be more than one!
174 for gcda
in ${objdir}/${dir}/.libs/*_la-${base}.gcda
; do
178 for gcno
in ${objdir}/${dir}/.libs/*_la-${base}.gcno
; do
181 [[ -n $gcno && -f $gcno ]] && ln -f "$gcno" "${objdir}/${dir}/.libs/${base}.gcno"
182 [[ -n $gcda && -f $gcda ]] && ln -f "$gcda" "${objdir}/${dir}/.libs/${base}.gcda"
183 if [[ ( -n $gcda && ! -f $gcda ) ||
( -n $gcno && ! -f $gcno ) ]]; then
184 $quiet ||
printf 'Warning: %s has no gcov notes file\n' "$f" 1>&2
189 if [[ -f ${objdir}/${dir}/.libs/${base}.gcda
]]; then
190 ((verbose
> 1)) && printf 'Running gcov for %s using gcda from .libs\n' "$f" 1>&2
191 if ! (cd "${objdir}/${f%/*}"; ((verbose > 2)) && set -vx; gcov -o .libs "${f##*/}") 1>&3; then
192 $quiet ||
printf 'Warning: gcov failed for %s\n' "$f" 1>&2
195 elif [[ -f ${objdir}/${dir}/${base}.gcda
]]; then
196 if ! (cd "${objdir}/${f%/*}"; ((verbose > 2)) && set -vx; gcov "${f##*/}") 1>&3; then
197 $quiet ||
printf 'Warning: gcov failed for %s\n' "$f" 1>&2
202 if [[ ! -f ${objdir}/${f}.gcov
]]; then
203 $quiet ||
printf 'Warning: gcov did not produce a .gcov file for %s\n' "$f" 1>&2
207 md5
=$
(md5sum "${srcdir}/${f}")
210 jq
-Rn --arg sum "${md5}" --arg f
"$f" '
219 | if .[0]|endswith("#")
221 elif .[0]|endswith("-")
227 ' "${objdir}/${f}.gcov" >> "${d}/f"
230 function make_report
{
231 jq
-s --arg job
"$job" \
232 --arg ci
"${ci:-travis-ci}" \
233 --arg token
"$token" \
235 --arg branch
"$branch" \
236 --arg upstream
"$origin" \
237 --arg head "$(git log -n1 --format=%H)" \
238 --arg subject
"$(git log -n1 --format=%s)" \
239 --arg aN
"$(git log -n1 --format=%aN)" \
240 --arg ae
"$(git log -n1 --format=%ae)" \
241 --arg cN
"$(git log -n1 --format=%cN)" \
242 --arg ce
"$(git log -n1 --format=%ce)" \
244 service_job_id: $job,
252 committer_email: $ce,
265 if [[ -z $out ]]; then
267 make_report
> "${d}/out"
268 elif [[ $out = - ]]; then
271 make_report
> "${out}"
274 if $post && [[ $out != /dev
/stdout
]]; then
275 curl
-sfg -X POST
-F "json_file=@${d}/out" -F "Filename=json_file" \
276 https
://coveralls.io
/api
/v
1/jobs