|
2 | 2 | # SPDX-FileCopyrightText: 2025-2026 Mathieu Barbin <mathieu.barbin@gmail.com> |
3 | 3 | # SPDX-License-Identifier: MIT |
4 | 4 |
|
5 | | -DIRS_FILE="$(dirname "$0")/.headache.dirs" |
| 5 | +SCRIPT_DIR="$(dirname "$0")" |
| 6 | +EXCLUDE_FILE="${SCRIPT_DIR}/.headache.exclude" |
6 | 7 |
|
7 | | -if [ ! -f "$DIRS_FILE" ]; then |
8 | | - echo "Directory list file '$DIRS_FILE' not found!" >&2 |
9 | | - exit 1 |
| 8 | +# Build exclusion list from .headache.exclude. |
| 9 | +# Each line is a path prefix to recursively exclude. |
| 10 | +# Empty lines and lines starting with '#' are ignored. |
| 11 | +EXCLUDES=() |
| 12 | +if [ -f "$EXCLUDE_FILE" ]; then |
| 13 | + while IFS= read -r line; do |
| 14 | + [ -z "$line" ] && continue |
| 15 | + case "$line" in |
| 16 | + \#*) continue ;; |
| 17 | + esac |
| 18 | + EXCLUDES+=("$line") |
| 19 | + done < "$EXCLUDE_FILE" |
10 | 20 | fi |
11 | 21 |
|
12 | | -while IFS= read -r dir; do |
13 | | - # Ignore empty lines and lines starting with '#' |
14 | | - [ -z "$dir" ] && continue |
15 | | - case "$dir" in |
16 | | - \#*) continue ;; |
17 | | - esac |
18 | | - echo "Apply headache to directory ${dir}" |
19 | | - |
20 | | - # Use per-directory COPYING.HEADER if it exists, otherwise fall back to root |
21 | | - if [ -f "${dir}/COPYING.HEADER" ]; then |
22 | | - header="${dir}/COPYING.HEADER" |
| 22 | +# Check if a directory matches any exclusion pattern (recursive). |
| 23 | +is_excluded() { |
| 24 | + local dir="$1" |
| 25 | + for excl in "${EXCLUDES[@]}"; do |
| 26 | + if [[ "$dir" == "$excl" ]] || [[ "$dir" == "$excl"/* ]]; then |
| 27 | + return 0 |
| 28 | + fi |
| 29 | + done |
| 30 | + return 1 |
| 31 | +} |
| 32 | + |
| 33 | +# Find the nearest COPYING.HEADER by walking up from a directory. |
| 34 | +find_header() { |
| 35 | + local dir="$1" |
| 36 | + local current="$dir" |
| 37 | + while [ "$current" != "." ] && [ "$current" != "/" ]; do |
| 38 | + if [ -f "${current}/COPYING.HEADER" ]; then |
| 39 | + echo "${current}/COPYING.HEADER" |
| 40 | + return |
| 41 | + fi |
| 42 | + current="$(dirname "$current")" |
| 43 | + done |
| 44 | + # Fall back to root |
| 45 | + if [ -f "COPYING.HEADER" ]; then |
| 46 | + echo "COPYING.HEADER" |
23 | 47 | else |
24 | | - header="COPYING.HEADER" |
| 48 | + echo "No COPYING.HEADER found for ${dir}" >&2 |
| 49 | + return 1 |
| 50 | + fi |
| 51 | +} |
| 52 | + |
| 53 | +# Discover directories containing .ml or .mli files from tracked git files. |
| 54 | +dirs=$(git ls-files '*.ml' '*.mli' | xargs -n1 dirname | sort -u) |
| 55 | + |
| 56 | +for dir in $dirs; do |
| 57 | + if is_excluded "$dir"; then |
| 58 | + echo "Skipping excluded directory: ${dir}" |
| 59 | + continue |
25 | 60 | fi |
26 | 61 |
|
| 62 | + header=$(find_header "$dir") |
| 63 | + echo "Apply headache to directory ${dir} (header: ${header})" |
| 64 | + |
27 | 65 | # Apply headache to .ml files |
28 | | - headache -c .headache.config -h "${header}" "${dir}"/*.ml |
| 66 | + if ls "${dir}"/*.ml 1> /dev/null 2>&1; then |
| 67 | + headache -c .headache.config -h "${header}" "${dir}"/*.ml |
| 68 | + fi |
29 | 69 |
|
30 | | - # Check if .mli files exist in the directory, if so apply headache |
| 70 | + # Apply headache to .mli files |
31 | 71 | if ls "${dir}"/*.mli 1> /dev/null 2>&1; then |
32 | 72 | headache -c .headache.config -h "${header}" "${dir}"/*.mli |
33 | 73 | fi |
34 | | -done < "$DIRS_FILE" |
| 74 | +done |
35 | 75 |
|
36 | 76 | dune fmt |
0 commit comments