1+ #! /usr/bin/env bash
2+ # SPDX-License-Identifier: BSD-3-Clause
3+ # Copyright 2016-2022, Intel Corporation
4+
5+ # check-headers.sh - check copyright and license in source files
6+
7+ SELF=$0
8+
9+ function usage() {
10+ echo " Usage: $SELF <source_root_path> <license_tag> [-h|-v|-a]"
11+ echo " -h, --help this help message"
12+ echo " -v, --verbose verbose mode"
13+ echo " -a, --all check all files (only modified files are checked by default)"
14+ echo " -d, --update_dates change Copyright dates in all analyzed files (rather not use with -a)"
15+ }
16+
17+ if [ " $# " -lt 2 ]; then
18+ usage >&2
19+ exit 2
20+ fi
21+
22+ SOURCE_ROOT=$1
23+ shift
24+ LICENSE=$1
25+ shift
26+
27+ PATTERN=` mktemp`
28+ TMP=` mktemp`
29+ TMP2=` mktemp`
30+ TEMPFILE=` mktemp`
31+ rm -f $PATTERN $TMP $TMP2
32+
33+ if [ " $1 " == " -h" -o " $1 " == " --help" ]; then
34+ usage
35+ exit 0
36+ fi
37+
38+ export GIT=" git -C ${SOURCE_ROOT} "
39+ $GIT rev-parse || exit 1
40+
41+ if [ -f $SOURCE_ROOT /.git/shallow ]; then
42+ SHALLOW_CLONE=1
43+ echo
44+ echo " Warning: This is a shallow clone. Checking dates in copyright headers"
45+ echo " will be skipped in case of files that have no history."
46+ echo
47+ else
48+ SHALLOW_CLONE=0
49+ fi
50+
51+ VERBOSE=0
52+ CHECK_ALL=0
53+ UPDATE_DATES=0
54+ while [ " $1 " != " " ]; do
55+ case $1 in
56+ -v|--verbose)
57+ VERBOSE=1
58+ ;;
59+ -a|--all)
60+ CHECK_ALL=1
61+ ;;
62+ -d|--update_dates)
63+ UPDATE_DATES=1
64+ ;;
65+ esac
66+ shift
67+ done
68+
69+ if [ $CHECK_ALL -eq 0 ]; then
70+ CURRENT_COMMIT=$( $GIT log --pretty=%H -1)
71+ MERGE_BASE=$( $GIT merge-base HEAD origin/master 2> /dev/null)
72+ [ -z $MERGE_BASE ] && \
73+ MERGE_BASE=$( $GIT log --pretty=" %cN:%H" | grep GitHub | head -n1 | cut -d: -f2)
74+ [ -z $MERGE_BASE -o " $CURRENT_COMMIT " = " $MERGE_BASE " ] && \
75+ CHECK_ALL=1
76+ fi
77+
78+ if [ $CHECK_ALL -eq 1 ]; then
79+ echo " INFO: Checking copyright headers of all files..."
80+ GIT_COMMAND=" ls-tree -r --name-only HEAD"
81+ else
82+ echo " INFO: Checking copyright headers of modified files only..."
83+ GIT_COMMAND=" diff --name-only $MERGE_BASE $CURRENT_COMMIT "
84+ fi
85+
86+ FILES=$( $GIT $GIT_COMMAND | ${SOURCE_ROOT} /utils/check_license/file-exceptions.sh | \
87+ grep -E -e ' *\.[chs]$' -e ' *\.[ch]pp$' -e ' *\.sh$' -e ' *\.py$' \
88+ -e ' TEST*' -e ' Makefile*' -e ' CMakeLists.txt$' -e ' *\.cmake$' \
89+ -e ' *\.link$' -e ' *\.map$' -e ' *\.Dockerfile$' -e ' LICENSE$' \
90+ -e ' /common.inc$' -e ' /match$' -e ' /check_whitespace$' -e ' /cppstyle$' | \
91+ xargs)
92+
93+ RV=0
94+ for file in $FILES ; do
95+ if [ $VERBOSE -eq 1 ]; then
96+ echo " Checking file: $file "
97+ fi
98+ # The src_path is a path which should be used in every command except git.
99+ # git is called with -C flag so filepaths should be relative to SOURCE_ROOT
100+ src_path=" ${SOURCE_ROOT} /$file "
101+ [ ! -f $src_path ] && continue
102+ # ensure that file is UTF-8 encoded
103+ ENCODING=` file -b --mime-encoding $src_path `
104+ iconv -f $ENCODING -t " UTF-8" $src_path > $TEMPFILE
105+
106+ if ! grep -q " SPDX-License-Identifier: $LICENSE " $src_path ; then
107+ echo >&2 " error: no $LICENSE SPDX tag in file: $src_path "
108+ RV=1
109+ fi
110+
111+ if [ $SHALLOW_CLONE -eq 0 ]; then
112+ $GIT log --no-merges --format=" %ai %aE" -- $file | sort > $TMP
113+ else
114+ # mark the grafted commits (commits with no parents)
115+ $GIT log --no-merges --format=" %ai %aE grafted-%p-commit" -- $file | sort > $TMP
116+ fi
117+
118+ # skip checking dates for non-Intel commits
119+ [[ ! $( tail -n1 $TMP ) =~ " @intel.com" ]] && continue
120+
121+ # skip checking dates for new files
122+ [ $( cat $TMP | wc -l) -le 1 ] && continue
123+
124+ # grep out the grafted commits (commits with no parents)
125+ # and skip checking dates for non-Intel commits
126+ grep -v -e " grafted--commit" $TMP | grep -e " @intel.com" > $TMP2
127+
128+ [ $( cat $TMP2 | wc -l) -eq 0 ] && continue
129+
130+ FIRST=` head -n1 $TMP2 `
131+ LAST=` tail -n1 $TMP2 `
132+
133+ YEARS=` sed '
134+ /Copyright [0-9-]\+.*, Intel Corporation/!d
135+ s/.*Copyright \([0-9]\+\)-\([0-9]\+\),.*/\1-\2/
136+ s/.*Copyright \([0-9]\+\),.*/\1-\1/' $src_path `
137+ if [ -z " $YEARS " ]; then
138+ echo >&2 " No copyright years in $src_path "
139+ RV=1
140+ continue
141+ fi
142+
143+ HEADER_FIRST=` echo $YEARS | cut -d" -" -f1`
144+ HEADER_LAST=` echo $YEARS | cut -d" -" -f2`
145+
146+ COMMIT_FIRST=` echo $FIRST | cut -d" -" -f1`
147+ COMMIT_LAST=` echo $LAST | cut -d" -" -f1`
148+ if [ " $COMMIT_FIRST " != " " -a " $COMMIT_LAST " != " " ]; then
149+ if [ $HEADER_LAST -lt $COMMIT_LAST ]; then
150+ if [ $HEADER_FIRST -lt $COMMIT_FIRST ]; then
151+ COMMIT_FIRST=$HEADER_FIRST
152+ fi
153+ COMMIT_LAST=` date +%G`
154+ if [ $COMMIT_FIRST -eq $COMMIT_LAST ]; then
155+ NEW=$COMMIT_LAST
156+ else
157+ NEW=$COMMIT_FIRST -$COMMIT_LAST
158+ fi
159+ if [ ${UPDATE_DATES} -eq 1 ]; then
160+ sed -i " s/Copyright ${YEARS} /Copyright ${NEW} /g" " ${src_path} "
161+ else
162+ echo " $file :1: error: wrong copyright date: (is: $YEARS , should be: $NEW )" >&2
163+ RV=1
164+ fi
165+ fi
166+ else
167+ echo " error: unknown commit dates in file: $file " >&2
168+ RV=1
169+ fi
170+ done
171+ rm -f $TMP $TMP2 $TEMPFILE
172+
173+ # check if error found
174+ if [ $RV -eq 0 ]; then
175+ echo " Copyright headers are OK."
176+ else
177+ echo " Error(s) in copyright headers found!" >&2
178+ fi
179+ exit $RV
0 commit comments