1#! /bin/sh
2
3# BSD LICENSE
4#
5# Copyright 2015 6WIND S.A.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11#   * Redistributions of source code must retain the above copyright
12#     notice, this list of conditions and the following disclaimer.
13#   * Redistributions in binary form must reproduce the above copyright
14#     notice, this list of conditions and the following disclaimer in
15#     the documentation and/or other materials provided with the
16#     distribution.
17#   * Neither the name of 6WIND S.A. nor the names of its
18#     contributors may be used to endorse or promote products derived
19#     from this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33# Do some basic checks in MAINTAINERS file
34
35cd $(dirname $0)/..
36
37# speed up by ignoring Unicode details
38export LC_ALL=C
39
40# Get files matching paths with wildcards and / meaning recursing
41files () # <path> [<path> ...]
42{
43	if [ -z "$1" ] ; then
44		return
45	fi
46	if [ -d .git ] ; then
47		git ls-files "$1"
48	else
49		find "$1" -type f |
50		sed 's,^\./,,'
51	fi |
52	# if not ended by /
53	if ! echo "$1" | grep -q '/[[:space:]]*$' ; then
54		# filter out deeper directories
55		sed "/\(\/[^/]*\)\{$(($(echo "$1" | grep -o / | wc -l) + 1))\}/d"
56	else
57		cat
58	fi
59	# next path
60	shift
61	files "$@"
62}
63
64# Get all files matching F: and X: fields
65parse_fx () # <index file>
66{
67	IFS='
68'
69	# parse each line excepted underlining
70	for line in $( (sed '/^-\+$/d' $1 ; echo) | sed 's,^$,§,') ; do
71		if echo "$line" | grep -q '^§$' ; then
72			# empty line delimit end of section
73			whitelist=$(files $flines)
74			blacklist=$(files $xlines)
75			match=$(aminusb "$whitelist" "$blacklist")
76			if [ -n "$whitelist" ] ; then
77				printf "# $title "
78				maintainers=$(echo "$maintainers" | sed -r 's,.*<(.*)>.*,\1,')
79				maintainers=$(printf "$maintainers" | sed -e 's,^,<,' -e 's,$,>,')
80				echo $maintainers
81			fi
82			if [ -n "$match" ] ; then
83				echo "$match"
84			fi
85			# flush section
86			unset maintainers
87			unset flines
88			unset xlines
89		elif echo "$line" | grep -q '^[A-Z]: ' ; then
90			# maintainer
91			maintainers=$(add_line_to_if "$line" "$maintainers" 'M: ')
92			# file matching pattern
93			flines=$(add_line_to_if "$line" "$flines" 'F: ')
94			# file exclusion pattern
95			xlines=$(add_line_to_if "$line" "$xlines" 'X: ')
96		else # assume it is a title
97			title="$line"
98		fi
99	done
100}
101
102# Check patterns in F: and X:
103check_fx () # <index file>
104{
105	IFS='
106'
107	for line in $(sed -n 's,^[FX]: ,,p' $1 | tr '*' '#') ; do
108		line=$(printf "$line" | tr '#' '*')
109		match=$(files "$line")
110		if [ -z "$match" ] ; then
111			echo "$line"
112		fi
113	done
114}
115
116# Add a line to a set of lines if it begins with right pattern
117add_line_to_if () # <new line> <lines> <head pattern>
118{
119	(
120		echo "$2"
121		echo "$1" | sed -rn "s,^$3(.*),\1,p"
122	) |
123	sed '/^$/d'
124}
125
126# Subtract two sets of lines
127aminusb () # <lines a> <lines b>
128{
129	printf "$1\n$2\n$2" | sort | uniq -u | sed '/^$/d'
130}
131
132printf 'sections: '
133parsed=$(parse_fx MAINTAINERS)
134echo "$parsed" | grep -c '^#'
135printf 'with maintainer: '
136echo "$parsed" | grep -c '^#.*@'
137printf 'maintainers: '
138grep '^M:.*<' MAINTAINERS | sort -u | wc -l
139
140echo
141echo '##########'
142echo '# orphan areas'
143echo '##########'
144echo "$parsed" | sed -rn 's,^#([^@]*)$,\1,p' | uniq
145
146echo
147echo '##########'
148echo '# files not listed'
149echo '##########'
150all=$(files ./)
151listed=$(echo "$parsed" | sed '/^#/d' | sort -u)
152aminusb "$all" "$listed"
153
154echo
155echo '##########'
156echo '# wrong patterns'
157echo '##########'
158check_fx MAINTAINERS
159
160# TODO: check overlaps
161