]> git.ipfire.org Git - thirdparty/squid.git/blob - scripts/source-maintenance.sh
ea2d890f56c4f61a7a8aff1a0d9d820bc7421610
[thirdparty/squid.git] / scripts / source-maintenance.sh
1 #!/bin/sh
2 #
3 ## Copyright (C) 1996-2025 The Squid Software Foundation and contributors
4 ##
5 ## Squid software is distributed under GPLv2+ license and includes
6 ## contributions from numerous individuals and organizations.
7 ## Please see the COPYING and CONTRIBUTORS files for details.
8 ##
9
10 #
11 # This script contains the code run to perform automatic source maintenance
12 # on Squid
13 #
14
15 # whether to continue execution after a failure
16 # TODO: Expand the subset of failures covered by this feature; see run_().
17 KeepGoing="no"
18 # the actual name of the directive that enabled keep-going mode
19 KeepGoingDirective=""
20
21 #
22 # The script checks that the version of astyle is TargetAstyleVersion.
23 # if it isn't, the default behaviour is to not perform the formatting stage
24 # in order to avoid unexpected massive changes if the behaviour of astyle
25 # has changed in different releases.
26 # if --with-astyle /path/to/astyle is used, the check is still performed
27 # and a warning is printed, but the sources are reformatted
28 TargetAstyleVersion="3.1"
29 ASTYLE='astyle'
30
31 # whether to check and, if necessary, update boilerplate copyright years
32 CheckAndUpdateCopyright=yes
33
34 # How to sync CONTRIBUTORS with the current git branch commits:
35 # * never: Do not update CONTRIBUTORS at all.
36 # * auto: Check commits added since the last similar update.
37 # * SHA1/etc: Check commits added after the specified git commit.
38 UpdateContributorsSince=auto
39
40 # --only-changed-since point
41 OnlyChangedSince=""
42
43 printUsage () {
44 cat <<USAGE_
45 Usage: $0 [option...]
46 options:
47 --check-and-update-copyright <yes|no> (default: yes)
48 --help|-h
49 --keep-going|-k (default: stop on error)
50 --only-changed-since <fork|commit> (default: apply to all files)
51 --update-contributors-since <never|auto|revision> (default: auto)
52 --with-astyle </path/to/astyle/executable> (default: astyle-${TargetAstyleVersion} or astyle)
53
54 USAGE_
55 }
56
57 printHelp () {
58
59 cat <<HELP_INTRO_
60 This script applies Squid mandatory code style guidelines and generates
61 various files derived from Squid sources.
62 HELP_INTRO_
63
64 printUsage
65
66 cat <<HELP_MAIN_
67 --help, -h
68
69 Print this information and exit.
70
71 --only-changed-since <"fork"|commit>
72
73 When specifieid, the script only examines for formatting changes those
74 files that have changed since the specified git reference point. The
75 argument is either a git commit (fed to "git diff") or a special keyword
76 "fork". Common commit values include HEAD^, master, origin/master, and the
77 branch the current one was forked off. When "fork" is specified, the
78 script will look for files changed since the current branch was forked off
79 upstream/master (according to "git merge-base --fork-point").
80
81 This option does not disable some repository-wide file generation and
82 repository-wide non-formatting checks/adjustments.
83
84 --update-contributors-since <never|auto|revision>
85
86 Configures how to sync CONTRIBUTORS with the current git branch commits:
87 * never: Do not update CONTRIBUTORS at all.
88 * auto: Check commits added since the last similar update.
89 * SHA1/etc: Check commits added after the specified git commit.
90
91 --with-astyle </path/to/astyle/executable>
92
93 Squid code style guidelines require astyle version $TargetAstyleVersion.
94 The path to the astyle binary can be specified using this command line
95 option or by exporting the ASTYLE environment variable. If both are
96 specified, the command-line option wins.
97
98 External dependencies:
99
100 * Astyle. See the --with-astyle command line option above.
101 * gperf (if you modify certain source files)
102
103 HELP_MAIN_
104 }
105
106 # command-line options
107 while [ $# -ge 1 ]; do
108 case "$1" in
109 --keep-going|-k)
110 KeepGoing=yes
111 KeepGoingDirective=$1
112 shift
113 ;;
114 --check-and-update-copyright)
115 if test "x$2" != xyes -a "x$2" != xno
116 then
117 printUsage
118 echo "Error: Option $1 expects a yes or no argument but got $2"
119 exit 1
120 fi
121 CheckAndUpdateCopyright=$2
122 shift 2
123 ;;
124 --update-contributors-since)
125 if test "x$2" = x
126 then
127 printUsage
128 echo "Error: Option $1 expects an argument."
129 exit 1
130 fi
131 UpdateContributorsSince="$2"
132 shift 2
133 ;;
134 --help|-h)
135 printHelp
136 exit 0
137 ;;
138 --with-astyle)
139 ASTYLE=$2
140 shift 2
141 ;;
142 --only-changed-since)
143 OnlyChangedSince="$2"
144 shift 2
145 ;;
146 *)
147 printUsage
148 echo "Unsupported command-line option: $1"
149 exit 1
150 ;;
151 esac
152 done
153
154 # an error code seen by a KeepGoing-aware command (or zero)
155 SeenErrors=0
156
157 if ! git diff --quiet; then
158 echo "There are unstaged changes. This script may modify sources."
159 echo "Stage changes to avoid permanent losses when things go bad."
160 exit 1
161 fi
162
163 # usage: <well-known program name> <program argument(s)> <candidate name>...
164 # Finds the first working program among the given candidate program names.
165 # The found program name is returned via the $FoundProgram global:
166 FoundProgram=""
167 findProgram ()
168 {
169 wellKnown="$1"
170 shift
171 options="$1"
172 shift
173
174 for candidate in $*
175 do
176 if "$candidate" $options < /dev/null > /dev/null 2> /dev/null
177 then
178 echo "Found ${wellKnown}-like program: $candidate"
179 FoundProgram="$candidate"
180 return 0
181 fi
182 done
183
184 echo "ERROR: Failed to find a ${wellKnown}-like program; tried: $*"
185 FoundProgram=""
186 return 1
187 }
188
189 made="generated" # a hack: prevents $GeneratedByMe searches matching this file
190 GeneratedByMe="This file is $made by scripts/source-maintenance.sh."
191
192 if [ "x$ASTYLE" != "x" ] ; then
193 if ! "${ASTYLE}" --version > /dev/null 2> /dev/null ; then
194 echo "ERROR: Cannot run user-supplied astyle: ${ASTYLE}"
195 exit 1
196 fi
197 else
198 findProgram astyle --version astyle-${TargetAstyleVersion} astyle || exit $?
199 ASTYLE=$FoundProgram
200 fi
201
202 ASVER=`"${ASTYLE}" --version 2>&1 | grep -o -E "[0-9.]+"`
203 if test "${ASVER}" != "${TargetAstyleVersion}" ; then
204 if test "${ASTYLE}" = "astyle" ; then
205 echo "Astyle version problem. You have ${ASVER} instead of ${TargetAstyleVersion}"
206 echo "Formatting step skipped due to version mismatch"
207 ASVER=""
208 else
209 echo "WARNING: ${ASTYLE} is version ${ASVER} instead of ${TargetAstyleVersion}"
210 echo "Formatting anyway, please double check output before submitting"
211 fi
212 else
213 echo "Detected expected astyle version: ${ASVER}"
214 fi
215 CppFormatter=''
216 if test "${ASVER}"; then
217 CppFormatter="./scripts/format-cpp.pl --with-astyle ${ASTYLE}"
218 fi
219
220 if test "x$OnlyChangedSince" = "xfork" ; then
221 ForkPoint=`git merge-base --fork-point upstream/master`
222 if test "x$ForkPoint" = "x" ; then
223 echo "Could not identify fork point - sometimes it happens"
224 echo "Please specify commit-id explicitly"
225 exit 1
226 fi
227 OnlyChangedSince="$ForkPoint"
228 fi
229
230 if test $CheckAndUpdateCopyright = yes
231 then
232 COPYRIGHT_YEARS=`date +"1996-%Y"`
233 echo "s/1996-2[0-9]+ The Squid Software Foundation and contributors/${COPYRIGHT_YEARS} The Squid Software Foundation and contributors/g" >> boilerplate_fix.sed
234 fi
235
236 # executes the specified command
237 # in KeepGoing mode, remembers errors and hides them from callers
238 run_ ()
239 {
240 "$@" && return 0 # return on success
241 error=$?
242
243 if test $KeepGoing = no; then
244 return $error
245 fi
246
247 echo "ERROR: Continuing after a failure ($error) due to $KeepGoingDirective"
248 SeenErrors=$error # TODO: Remember the _first_ error instead
249 return 0 # hide error from the caller
250 }
251
252 updateIfChanged ()
253 {
254 original="$1"
255 updated="$2"
256 message="$3"
257
258 if ! cmp -s "${original}" "${updated}"; then
259 echo "NOTICE: File ${original} changed: ${message}"
260 run_ mv "${updated}" "${original}" || return
261 else
262 run_ rm -f "${updated}" || exit $?
263 fi
264 }
265
266 # uses the given script to update the given source file
267 applyPlugin ()
268 {
269 script="$1"
270 source="$2"
271
272 new="$source.new"
273 $script "$source" > "$new" &&
274 updateIfChanged "$source" "$new" "by $script"
275 }
276
277 # updates the given source file using the given script(s)
278 applyPluginsTo ()
279 {
280 source="$1"
281 shift
282
283 for script in `git ls-files "$@"`; do
284 run_ applyPlugin $script $source || return
285 done
286 }
287
288 # succeeds if all MakeNamedErrorDetail() names are unique
289 checkMakeNamedErrorDetails ()
290 {
291 problems=1 # assume there are problems until proven otherwise
292
293 options='-h --only-matching --extended-regexp'
294 git grep $options 'MakeNamedErrorDetail[(]"[^"]*"[)]' src |
295 sort |
296 uniq --count > \
297 MakeNamedErrorDetail.tmp
298
299 if grep --quiet --word-regexp 1 MakeNamedErrorDetail.tmp; then
300 if grep --invert-match --word-regexp 1 MakeNamedErrorDetail.tmp; then
301 echo "ERROR: Duplicated MakeNamedErrorDetail names (see above)."
302 else
303 problems=0
304 fi
305 else
306 echo "ERROR: Cannot find or process MakeNamedErrorDetail calls."
307 fi
308
309 rm MakeNamedErrorDetail.tmp # ignore (unexpected) cleanup failures
310 return $problems
311 }
312
313 # extract IDs and gists of cache_log_message debugs() in the given source file
314 collectDebugMessagesFrom ()
315 {
316 source="$1"
317 destination="doc/debug-messages.tmp"
318
319 if test "x$OnlyChangedSince" != "x"; then
320 # Skipping collection due to --only-changed-since.
321 # processDebugMessages() will warn.
322 return 0
323 fi
324
325 # Merge multi-line debugs() into one-liners and remove '//...' comments.
326 awk 'BEGIN { found=0; dbgLine=""; } {
327 if ($0 ~ /[ \t]debugs[ \t]*\(/)
328 found = 1;
329 if (found) {
330 commented = match($0, /\);[ \t]*\/\//);
331 if (commented)
332 $0 = substr($0, 1, RSTART+1);
333 dbgLine = dbgLine $0;
334 }
335 if ($0 ~ /\);/) {
336 if (found) {
337 found = 0;
338 print dbgLine;
339 dbgLine = "";
340 }
341 }
342 }' $source > doc/debug-messages.tmp2
343
344 # sed expressions:
345 # - replace debugs() prefix with the message ID contained in it
346 # - remove simple parenthesized non-"string" items like (a ? b : c)
347 # - replace any remaining non-"string" items with ...
348 # - remove quotes around "strings"
349 # - remove excessive whitespace
350 # - remove debugs() statement termination sugar
351 grep -o -E '\bdebugs[^,]*,[^,]*(Critical|Important)[(][0-9]+.*' doc/debug-messages.tmp2 | \
352 sed -r \
353 -e 's/.*(Critical|Important)[(]([0-9]+)[)][^,]*,\s*/\2 /' \
354 -e 's/<<\s*[(].*[)]\s*(<<|[)];)/<< ... \1/g' \
355 -e 's/<<\s*[^"]*/.../g' \
356 -e 's@([^\\])"@\1@g' \
357 -e 's/\s\s*/ /g' \
358 -e 's/[)];$//g' \
359 >> $destination
360
361 rm -f doc/debug-messages.tmp2
362 }
363
364 # make doc/debug-messages.dox from aggregate collectDebugMessagesFrom results
365 processDebugMessages ()
366 {
367 source="doc/debug-messages.tmp"
368 destination="doc/debug-messages.dox"
369
370 if test "x$OnlyChangedSince" != "x"; then
371 echo "WARNING: Skipping update of $destination due to --only-changed-since"
372 return 0
373 fi
374
375 if test '!' -s "$source"; then
376 echo "ERROR: Failed to find debugs() message IDs"
377 return 1
378 fi
379
380 repeatedIds=`awk '{print $1}' $source | sort -n | uniq -d`
381 if test "x$repeatedIds" != "x"; then
382 echo "ERROR: Repeated debugs() message IDs:"
383 echo "$repeatedIds"
384 echo ""
385 return 1
386 fi
387
388 repeatedGists=`awk '{$1=""; print substr($0,2)}' $source | sort | uniq -d`
389 if test "x$repeatedGists" != "x"; then
390 echo "ERROR: Repeated debugs() message gists:"
391 echo "$repeatedGists"
392 echo ""
393 return 1
394 fi
395
396 cat scripts/boilerplate.h > $destination
397 printf '/**\n' >> $destination
398 printf '\\page ControlledCacheLogMessages Message IDs and gists for cache_log_message\n' >> $destination
399 printf '\\verbatim\n' >> $destination
400 printf 'ID Message gist\n' >> $destination
401 printf '== ============\n' >> $destination
402 sort -n < $source >> $destination
403 printf '\\endverbatim\n' >> $destination
404 printf '*/\n' >> $destination
405
406 rm -f $source
407 }
408
409 # make doc/debug-sections.txt from aggregated by srcFormat extracts
410 processDebugSections ()
411 {
412 destination="doc/debug-sections.txt"
413
414 if test "x$OnlyChangedSince" != "x"; then
415 echo "WARNING: Skipping update of $destination due to --only-changed-since"
416 return 0
417 fi
418
419 LC_ALL=C sort -u < doc/debug-sections.tmp > doc/debug-sections.tmp2
420
421 cat scripts/boilerplate.h > $destination
422 echo "" >> $destination
423 cat doc/debug-sections.tmp2 >> $destination
424
425 rm -f doc/debug-sections.tmp*
426 }
427
428 srcFormat ()
429 {
430 # remove stale temporary files that accumulate info extracted below
431 rm -f doc/debug-messages.tmp*
432 rm -f doc/debug-sections.tmp*
433
434 #
435 # Scan for incorrect use of #ifdef/#ifndef
436 #
437 git grep "ifn?def .*_SQUID_" |
438 grep -v -E "_H$" |
439 grep -v "scripts/source-maintenance.sh" |
440 while read f; do echo "PROBLEM?: ${f}"; done
441
442 #
443 # Scan for file-specific actions
444 #
445
446 # The two git commands below will also list any files modified during the
447 # current run (e.g., src/http/RegisteredHeadersHash.cci or icons/icon.am).
448 FilesToOperateOn=""
449 if test "x$OnlyChangedSince" != "x" ; then
450 FilesToOperateOn=`git diff --name-only $OnlyChangedSince`
451 gitResult=$?
452 if test $gitResult -ne 0 ; then
453 echo "ERROR: Cannot use --only-changed-since reference point: $OnlyChangedSince"
454 echo "Consider using a git commit SHA (from git log) instead"
455 return $gitResult
456 fi
457 else
458 FilesToOperateOn=`git ls-files`
459 gitResult=$?
460 # a bit paranoid but protects the empty $FilesToOperateOn check below
461 if test $gitResult -ne 0 ; then
462 echo "ERROR: Cannot find source code file names"
463 return $gitResult
464 fi
465 fi
466 if test "x$FilesToOperateOn" = "x"; then
467 echo "WARNING: No files to scan and format"
468 return 0
469 fi
470
471 for FILENAME in $FilesToOperateOn; do
472 skip_copyright_check=""
473
474 # skip subdirectories, git ls-files is recursive
475 test -d $FILENAME && continue
476
477 # generated files are formatted during their generation
478 if grep -q -F "$GeneratedByMe" ${FILENAME}; then
479 continue
480 fi
481
482 case ${FILENAME} in
483
484 *.h|*.c|*.cc|*.cci)
485
486 #
487 # Code Style formatting maintenance
488 #
489 applyPluginsTo ${FILENAME} scripts/maintenance/ || return
490 if test "$CppFormatter"; then
491 if $CppFormatter $FILENAME > $FILENAME.new; then
492 updateIfChanged $FILENAME $FILENAME.new 'by astyle'
493 else
494 rm $FILENAME.new
495 fi
496 fi
497
498 #
499 # REQUIRE squid.h first #include
500 #
501 case ${FILENAME} in
502 src/cf_gen.cc)
503 # ignore, this is a build tool.
504 ;;
505 *.c|*.cc)
506 FI=`grep "#include" ${FILENAME} | head -1`;
507 if test "${FI}" != "#include \"squid.h\"" -a "${FILENAME}" != "cf_gen.cc"; then
508 echo "ERROR: ${FILENAME} does not include squid.h first!"
509 fi
510 ;;
511 *.h|*.cci)
512 FI=`grep "#include \"squid.h\"" ${FILENAME}`;
513 if test "x${FI}" != "x" ; then
514 echo "ERROR: ${FILENAME} duplicate include of squid.h"
515 fi
516 ;;
517 esac
518
519 #
520 # If a file includes openssl headers, then it must include compat/openssl.h
521 #
522 if test "${FILENAME}" != "compat/openssl.h"; then
523 FA=`grep "#include.*openssl/" "${FILENAME}" 2>/dev/null | head -1`;
524 FB=`grep '#include.*compat/openssl[.]h' "${FILENAME}" 2>/dev/null | head -1`;
525 if test "x${FA}" != "x" -a "x${FB}" = "x"; then
526 echo "ERROR: ${FILENAME} includes openssl headers without including \"compat/openssl.h\""
527 fi
528 fi
529
530 #
531 # forward.h means different things to Squid code depending on the path
532 # require the full path is explicit for every include
533 #
534 FI=`grep "#include \"forward.h\"" ${FILENAME}`;
535 if test "x${FI}" != "x" ; then
536 echo "ERROR: ${FILENAME} contains reference to forward.h without path"
537 fi
538
539 #
540 # detect functions unsafe for use within Squid.
541 # strdup() - only allowed in compat/xstring.h which defines a safe replacement.
542 # sprintf() - not allowed anywhere.
543 #
544 STRDUP=`grep -e "[^x]strdup(" ${FILENAME}`;
545 if test "x${STRDUP}" != "x" -a "${FILENAME}" != "compat/xstring.h"; then
546 echo "ERROR: ${FILENAME} contains unprotected use of strdup()"
547 fi
548 SPRINTF=`grep -e "[^v]sprintf(" ${FILENAME}`;
549 if test "x${SPRINTF}" != "x" ; then
550 echo "ERROR: ${FILENAME} contains unsafe use of sprintf()"
551 fi
552
553 collectDebugMessagesFrom ${FILENAME}
554
555 #
556 # DEBUG Section list maintenance
557 #
558 grep " DEBUG: section" <${FILENAME} | sed -e 's/ \* DEBUG: //' -e 's%/\* DEBUG: %%' -e 's% \*/%%' >> doc/debug-sections.tmp
559
560 #
561 # File permissions maintenance.
562 #
563 chmod 644 ${FILENAME}
564 ;;
565
566 *.pl|*.sh)
567 #
568 # File permissions maintenance.
569 #
570 chmod 755 ${FILENAME}
571 ;;
572
573 *.am)
574 applyPluginsTo ${FILENAME} scripts/format-makefile-am.pl || return
575 ;;
576
577 ChangeLog|CREDITS|CONTRIBUTORS|COPYING|*.png|*.po|*.pot|rfcs/|*.txt|test-suite/squidconf/empty|.bzrignore)
578 # we do not enforce copyright blurbs in:
579 #
580 # Squid Project contributor attribution file
581 # third-party copyright attribution file
582 # images,
583 # translation PO/POT
584 # license documentation files
585 # (imported) plain-text documentation files and ChangeLogs
586 # VCS internal files
587 #
588 skip_copyright_check=1
589 ;;
590 esac
591
592 # check for Foundation copyright blurb
593 if test $CheckAndUpdateCopyright = yes -a -f ${FILENAME} -a "x$skip_copyright_check" = "x"; then
594 BLURB=`grep -o "${COPYRIGHT_YEARS} The Squid Software Foundation and contributors" ${FILENAME}`;
595 if test "x${BLURB}" = "x"; then
596 BOILER=`grep -o -E "1996-2[0-9]+ The Squid Software Foundation and contributors" ${FILENAME}`;
597 if test "x${BOILER}" != "x"; then
598 echo "UPDATE COPYRIGHT for ${FILENAME}"
599 sed --in-place -r -f boilerplate_fix.sed ${FILENAME}
600 else
601 echo "CHECK COPYRIGHT for ${FILENAME}"
602 fi
603 fi
604 fi
605
606 done
607
608 run_ processDebugSections || return
609 run_ processDebugMessages || return
610 }
611
612 printRawAmFile ()
613 {
614 sed -e 's%\ \*%##%; s%/\*%##%; s%##/%##%' < scripts/boilerplate.h
615
616 echo "## $GeneratedByMe"
617 echo
618
619 printf "%s =" "$1"
620 # Only some files are formed from *.po filenames, but all such files
621 # should list *.lang filenames instead.
622 git ls-files $2$3 | sed -e s%$2%%g -e 's%\.po%\.lang%g' | while read f; do
623 printf ' \\\n\t%s' "${f}"
624 done
625 printf '\n'
626 }
627
628 generateAmFile ()
629 {
630 amFile="$1"
631 shift
632
633 # format immediately/here instead of in srcFormat to avoid misleading
634 # "NOTICE: File ... changed by scripts/format-makefile-am.pl" in srcFormat
635 printRawAmFile "$@" | scripts/format-makefile-am.pl > $amFile.new
636
637 # Distinguishing generation-only changes from formatting-only changes is
638 # difficult, so we only check/report cumulative changes. Most interesting
639 # changes are triggered by printRawAmFile() finding new entries.
640 updateIfChanged $amFile $amFile.new 'by generateAmFile()'
641 }
642
643 # Build icons install include from current icons available
644 generateAmFile icons/icon.am ICONS "icons/" "silk/*"
645
646 # Build templates install include from current templates available
647 generateAmFile errors/template.am ERROR_TEMPLATES "errors/" "templates/ERR_*"
648
649 # Build errors translation install include from current .PO available
650 generateAmFile errors/language.am LANGUAGE_FILES "errors/" "*.po"
651
652 # Build manuals translation install include from current .PO available
653 generateAmFile doc/manuals/language.am LANGUAGE_FILES "doc/manuals/" "*.po"
654
655 # Build STUB framework include from current stub_* available
656 generateAmFile src/tests/Stub.am STUB_SOURCE "src/" "tests/stub_*.cc"
657
658 generateRawGperfFile ()
659 {
660 gperfFile="$1"
661
662 echo "/* $GeneratedByMe */"
663 echo
664
665 if test `gperf --version | head -1 | cut -d ' ' -f 3 | cut -d. -f '-2' | sed -e 's/\.//'` -lt 32 ; then
666 # We configure C++ compilers to complain about missing '[[fallthrough]]' attribute
667 # where old gperf versions use a '/*FALLTHROUGH*/' code comment.
668 (cd `dirname $gperfFile` && gperf -m 100000 `basename $gperfFile`) | \
669 sed -e 's@/[*]FALLTHROUGH[*]/@[[fallthrough]];@g'
670 else
671 # gperf 3.2+ provide fallthrough attributes
672 (cd `dirname $gperfFile` && gperf -m 100000 `basename $gperfFile`)
673 fi
674 }
675
676 generateGperfFile ()
677 {
678 gperfFile="$1"
679 cciFile=`echo $gperfFile | sed 's/[.]gperf$/.cci/'`
680
681 if test $gperfFile -ot $cciFile; then
682 return 0
683 fi
684
685 generateRawGperfFile $gperfFile > $cciFile.unformatted || return
686
687 if test "$CppFormatter"; then
688 # generateAmFile() explains why we format immediately/here
689 $CppFormatter $cciFile.unformatted > $cciFile.new || return
690 rm $cciFile.unformatted
691 else
692 echo "ERROR: Source code formatting disabled, but regenerated $cciFile needs formatting"
693 mv $cciFile.unformatted $cciFile.new || return
694 fi
695
696 # generateAmFile() explains why we only check/report cumulative changes
697 updateIfChanged $cciFile $cciFile.new 'by generateGperfFile()'
698 }
699
700 run_ generateGperfFile src/http/RegisteredHeadersHash.gperf || exit 1
701
702 run_ checkMakeNamedErrorDetails || exit 1
703
704 # This function updates CONTRIBUTORS based on the recent[1] branch commit log.
705 # Fresh contributor entries are filtered using the latest vetted CONTRIBOTORS
706 # file on the current branch. The following CONTRIBUTORS commits are
707 # considered vetted:
708 #
709 # * authored (in "git log --author" sense) by squidadm,
710 # * matching (in "git log --grep" sense) $vettedCommitPhraseRegex set below.
711 #
712 # A human authoring an official GitHub pull request containing a new
713 # CONTRIBUTORS version (that they want to be used as a new vetting point)
714 # should add a phrase matching $vettedCommitPhraseRegex to the PR description.
715 #
716 # [1] As defined by the --update-contributors-since script parameter.
717 collectAuthors ()
718 {
719 if test "x$UpdateContributorsSince" = xnever
720 then
721 return 0 # successfully did nothing, as requested
722 fi
723
724 vettedCommitPhraseRegex='[Rr]eference point for automated CONTRIBUTORS updates'
725
726 since="$UpdateContributorsSince"
727 if test "x$UpdateContributorsSince" = xauto
728 then
729 # find the last CONTRIBUTORS commit vetted by a human
730 humanSha=`git log -n1 --format='%H' --grep="$vettedCommitPhraseRegex" CONTRIBUTORS`
731 # find the last CONTRIBUTORS commit attributed to this script
732 botSha=`git log -n1 --format='%H' --author=squidadm CONTRIBUTORS`
733 if test "x$humanSha" = x && test "x$botSha" = x
734 then
735 echo "ERROR: Unable to determine the commit to start contributors extraction from"
736 return 1
737 fi
738
739 # find the latest commit among the above one or two commits
740 if test "x$humanSha" = x
741 then
742 since=$botSha
743 elif test "x$botSha" = x
744 then
745 since=$humanSha
746 elif git merge-base --is-ancestor $humanSha $botSha
747 then
748 since=$botSha
749 else
750 since=$humanSha
751 fi
752 echo "Collecting contributors since $since"
753 fi
754 range="$since..HEAD"
755
756 # We add four leading spaces below to mimic CONTRIBUTORS entry style.
757 # add commit authors:
758 git log --format=' %an <%ae>' $range > authors.tmp
759 # add commit co-authors:
760 git log $range | \
761 grep -Ei '^[[:space:]]*Co-authored-by:' | \
762 sed -r 's/^\s*Co-authored-by:\s*/ /i' >> authors.tmp
763 # but do not add committers (--format=' %cn <%ce>').
764
765 # add collected new (co-)authors, if any, to CONTRIBUTORS
766 if ./scripts/update-contributors.pl --quiet < authors.tmp > CONTRIBUTORS.new
767 then
768 updateIfChanged CONTRIBUTORS CONTRIBUTORS.new \
769 "A human PR description should match: $vettedCommitPhraseRegex"
770 fi
771 result=$?
772
773 rm -f authors.tmp
774 return $result
775 }
776
777 # Update CONTRIBUTORS content
778 run_ collectAuthors || exit 1
779
780 # Run formatting
781 srcFormat || exit 1
782
783 test -e boilerplate_fix.sed && rm -f boilerplate_fix.sed
784
785 exit $SeenErrors