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