xref: /illumos-gate/usr/src/tools/scripts/check-gitignore.sh (revision 14e8f286dd05c4acf54ddb51d15afc0de471037b)
1*14e8f286SPatrick Mooney#!/bin/ksh
2*14e8f286SPatrick Mooney#
3*14e8f286SPatrick Mooney# This file and its contents are supplied under the terms of the
4*14e8f286SPatrick Mooney# Common Development and Distribution License ("CDDL"), version 1.0.
5*14e8f286SPatrick Mooney# You may only use this file in accordance with the terms of version
6*14e8f286SPatrick Mooney# 1.0 of the CDDL.
7*14e8f286SPatrick Mooney#
8*14e8f286SPatrick Mooney# A full copy of the text of the CDDL should have accompanied this
9*14e8f286SPatrick Mooney# source.  A copy of the CDDL is also available via the Internet at
10*14e8f286SPatrick Mooney# http://www.illumos.org/license/CDDL.
11*14e8f286SPatrick Mooney#
12*14e8f286SPatrick Mooney
13*14e8f286SPatrick Mooney#
14*14e8f286SPatrick Mooney# Copyright 2025 Oxide Computer Company
15*14e8f286SPatrick Mooney#
16*14e8f286SPatrick Mooney
17*14e8f286SPatrick Mooneyfunction cd_git_root
18*14e8f286SPatrick Mooney{
19*14e8f286SPatrick Mooney	git_root=$(git rev-parse --show-toplevel)
20*14e8f286SPatrick Mooney
21*14e8f286SPatrick Mooney	if [[ ! -d $git_root ]]; then
22*14e8f286SPatrick Mooney		echo "Must be run from within git repository"
23*14e8f286SPatrick Mooney		exit 1
24*14e8f286SPatrick Mooney	fi
25*14e8f286SPatrick Mooney
26*14e8f286SPatrick Mooney	cd $git_root
27*14e8f286SPatrick Mooney}
28*14e8f286SPatrick Mooney
29*14e8f286SPatrick Mooneyfunction check_stale
30*14e8f286SPatrick Mooney{
31*14e8f286SPatrick Mooney	cd_git_root
32*14e8f286SPatrick Mooney	awk -f - <<'EOF'
33*14e8f286SPatrick Mooneyfunction check_ignore(repo_root, path, seen_lines, printed_header)
34*14e8f286SPatrick Mooney{
35*14e8f286SPatrick Mooney	fp = repo_root "/" path;
36*14e8f286SPatrick Mooney	lnr = 0;
37*14e8f286SPatrick Mooney	found = 0;
38*14e8f286SPatrick Mooney	while (getline < (repo_root "/" path) > 0) {
39*14e8f286SPatrick Mooney		lnr += 1;
40*14e8f286SPatrick Mooney		original = $0;
41*14e8f286SPatrick Mooney		# trim comments
42*14e8f286SPatrick Mooney		sub(/#.*/, "");
43*14e8f286SPatrick Mooney		# and white space
44*14e8f286SPatrick Mooney		sub(/[ \t]+/, "");
45*14e8f286SPatrick Mooney
46*14e8f286SPatrick Mooney		if (length() == 0) {
47*14e8f286SPatrick Mooney			# skip empty lines
48*14e8f286SPatrick Mooney			continue;
49*14e8f286SPatrick Mooney		}
50*14e8f286SPatrick Mooney		if (/^!/) {
51*14e8f286SPatrick Mooney			# skip excludes
52*14e8f286SPatrick Mooney			continue;
53*14e8f286SPatrick Mooney		}
54*14e8f286SPatrick Mooney		if (seen_lines[lnr] == 0) {
55*14e8f286SPatrick Mooney			if (printed_header == 0) {
56*14e8f286SPatrick Mooney				print "Possible stale:" > "/dev/stderr"
57*14e8f286SPatrick Mooney				printed_header = 1;
58*14e8f286SPatrick Mooney			}
59*14e8f286SPatrick Mooney			printf "%s:%u\t%s\n", path, lnr, original;
60*14e8f286SPatrick Mooney			found += 1;
61*14e8f286SPatrick Mooney		}
62*14e8f286SPatrick Mooney	}
63*14e8f286SPatrick Mooney	return found;
64*14e8f286SPatrick Mooney}
65*14e8f286SPatrick Mooney
66*14e8f286SPatrick MooneyBEGIN {
67*14e8f286SPatrick Mooney	cmd_ignored_files = \
68*14e8f286SPatrick Mooney	"git ls-files -i -o -x '*' | git check-ignore -v --stdin --no-index";
69*14e8f286SPatrick Mooney	FS=":"
70*14e8f286SPatrick Mooney	while ((cmd_ignored_files | getline) > 0) {
71*14e8f286SPatrick Mooney		# If --verbose is specified, the output is a series of lines of the form:
72*14e8f286SPatrick Mooney		# <source> <COLON> <linenum> <COLON> <pattern> <HT> <pathname>
73*14e8f286SPatrick Mooney		seen_lines[$1][$2] = 1;
74*14e8f286SPatrick Mooney	}
75*14e8f286SPatrick Mooney
76*14e8f286SPatrick Mooney	nignore = 0;
77*14e8f286SPatrick Mooney	while (("git ls-files --full-name '*.gitignore'" | getline) > 0) {
78*14e8f286SPatrick Mooney		ignores[nignore] = $0;
79*14e8f286SPatrick Mooney		nignore += 1;
80*14e8f286SPatrick Mooney	}
81*14e8f286SPatrick Mooney
82*14e8f286SPatrick Mooney	"git rev-parse --show-toplevel" | getline repo_root
83*14e8f286SPatrick Mooney
84*14e8f286SPatrick Mooney	total = 0;
85*14e8f286SPatrick Mooney	for (n in ignores) {
86*14e8f286SPatrick Mooney		path = ignores[n];
87*14e8f286SPatrick Mooney		total += check_ignore(repo_root, path, seen_lines[path], total);
88*14e8f286SPatrick Mooney	}
89*14e8f286SPatrick Mooney}
90*14e8f286SPatrick MooneyEOF
91*14e8f286SPatrick Mooney}
92*14e8f286SPatrick Mooney
93*14e8f286SPatrick Mooneyfunction check_tracked
94*14e8f286SPatrick Mooney{
95*14e8f286SPatrick Mooney	cd_git_root
96*14e8f286SPatrick Mooney	echo "git-tracked files matched by gitignore:" 1>&2
97*14e8f286SPatrick Mooney	git ls-files | git check-ignore --no-index --stdin
98*14e8f286SPatrick Mooney}
99*14e8f286SPatrick Mooney
100*14e8f286SPatrick Mooney
101*14e8f286SPatrick MooneyUSAGE='Usage: check-gitignore <check>
102*14e8f286SPatrick Mooney
103*14e8f286SPatrick MooneyWhere <check> is one of:
104*14e8f286SPatrick Mooney	tracked	- Are any tracked files covered by a gitignore?
105*14e8f286SPatrick Mooney	stale	- Are there gitignore definitions which match no files?
106*14e8f286SPatrick Mooney'
107*14e8f286SPatrick Mooney
108*14e8f286SPatrick Mooneycase $1 in
109*14e8f286SPatrick Mooney	tracked )
110*14e8f286SPatrick Mooney		check_tracked
111*14e8f286SPatrick Mooney		;;
112*14e8f286SPatrick Mooney	stale )
113*14e8f286SPatrick Mooney		check_stale
114*14e8f286SPatrick Mooney		;;
115*14e8f286SPatrick Mooney	* )
116*14e8f286SPatrick Mooney		echo "$USAGE"
117*14e8f286SPatrick Mooney		exit 1
118*14e8f286SPatrick Mooney		;;
119*14e8f286SPatrick Mooneyesac
120