|
root / base / usr / src / tools / scripts / check-gitignore.sh
check-gitignore.sh Bash 120 lines 2.3 KB
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/bin/ksh
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2025 Oxide Computer Company
#

function cd_git_root
{
	git_root=$(git rev-parse --show-toplevel)

	if [[ ! -d $git_root ]]; then
		echo "Must be run from within git repository"
		exit 1
	fi

	cd $git_root
}

function check_stale
{
	cd_git_root
	awk -f - <<'EOF'
function check_ignore(repo_root, path, seen_lines, printed_header)
{
	fp = repo_root "/" path;
	lnr = 0;
	found = 0;
	while (getline < (repo_root "/" path) > 0) {
		lnr += 1;
		original = $0;
		# trim comments
		sub(/#.*/, "");
		# and white space
		sub(/[ \t]+/, "");

		if (length() == 0) {
			# skip empty lines
			continue;
		}
		if (/^!/) {
			# skip excludes
			continue;
		}
		if (seen_lines[lnr] == 0) {
			if (printed_header == 0) {
				print "Possible stale:" > "/dev/stderr"
				printed_header = 1;
			}
			printf "%s:%u\t%s\n", path, lnr, original;
			found += 1;
		}
	}
	return found;
}

BEGIN {
	cmd_ignored_files = \
	"git ls-files -i -o -x '*' | git check-ignore -v --stdin --no-index";
	FS=":"
	while ((cmd_ignored_files | getline) > 0) {
		# If --verbose is specified, the output is a series of lines of the form:
		# <source> <COLON> <linenum> <COLON> <pattern> <HT> <pathname>
		seen_lines[$1][$2] = 1;
	}

	nignore = 0;
	while (("git ls-files --full-name '*.gitignore'" | getline) > 0) {
		ignores[nignore] = $0;
		nignore += 1;
	}

	"git rev-parse --show-toplevel" | getline repo_root

	total = 0;
	for (n in ignores) {
		path = ignores[n];
		total += check_ignore(repo_root, path, seen_lines[path], total);
	}
}
EOF
}

function check_tracked
{
	cd_git_root
	echo "git-tracked files matched by gitignore:" 1>&2
	git ls-files | git check-ignore --no-index --stdin
}


USAGE='Usage: check-gitignore <check>

Where <check> is one of:
	tracked	- Are any tracked files covered by a gitignore?
	stale	- Are there gitignore definitions which match no files?
'

case $1 in
	tracked )
		check_tracked
		;;
	stale )
		check_stale
		;;
	* )
		echo "$USAGE"
		exit 1
		;;
esac