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
|