#!/usr/bin/env sh # # Закінчення рядків: чи не заліз у репозиторій CRLF. # # Навіщо окрема перевірка. За один день CRLF зламав дві різні речі, і # жодну з них не видно в diff: # # 1. gofmt почав друкувати як «не відформатовані» файли, яких ніхто не # чіпав: він вважає \r частиною рядка й пропонує переписати файл # цілком. Людина бачить червоне на чужому коді, і найкоротший вихід # із цього — `gofmt -w` — комітить зіпсовані переноси всім. # 2. db/profiles/build.py, запущений на Windows у текстовому режимі, # переписав згенеровану міграцію 0014 з \r\n. Байти інші → sha256 # інший, а netpulse-migrate звіряє суму вже застосованих міграцій і # зупиняє накат словами «міграцію змінено після застосування». # Тобто невидима зміна зупинила б оновлення на всіх стендах одразу. # Порівняння `build.py --check` цього НЕ ловить: Python читає # текстом і сам перекладає \r\n у \n ще до порівняння. # # Перевіряються дві різні речі, і ціна в них різна: # # ІНДЕКС (i/crlf) — те, що дістанеться всім і поїде на стенд. Це # помилка: скрипт падає. У CI це і є сторож. # РОБОЧА КОПІЯ (w/crlf) — біда однієї машини. У CI її не буває, бо # checkout свіжий; локально ж це рівно та причина, # через яку gofmt червоніє на чужому. Тому тут # попередження з підказкою, а з --strict (як у CI) # — теж падіння: у свіжому клоні на Linux такого # бути не може, і якщо воно є, зламаний checkout. # # .gitattributes оголошує «у репозиторії — завжди LF». Файли, яким LF не # призначено (*.ps1 з eol=crlf, двійкові), з перевірки виключені: у них # CRLF — не порушення, а оголошена норма. # # Запуск: # sh scripts/check-eol.sh # індекс — жорстко, робоча копія — попередження # sh scripts/check-eol.sh --strict # обидва жорстко (так робить CI) # # Полагодити: # індекс: git add --renormalize . && git commit # робоча копія: git config core.autocrlf false # git rm --cached -r . && git reset --hard set -u # CDPATH= — не помилка з пробілом, а гасіння CDPATH: якщо він виставлений # в оточенні, cd мовчки піде не туди, і скрипт перевірятиме чужий каталог. # shellcheck disable=SC1007 ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) cd "$ROOT" || exit 1 STRICT=0 if [ "${1:-}" = "--strict" ]; then STRICT=1 fi # `git ls-files --eol` друкує «i/xx w/xx attr/… шлях»: розділювач # перед шляхом — саме табуляція, тому шляхи з пробілами не розсипаються. list=$(git ls-files --eol) || { echo "check-eol: git ls-files не спрацював — це взагалі репозиторій?" >&2 exit 2 } idx=$(printf '%s\n' "$list" | awk -F'\t' ' { split($1, c, " ") if (c[1] == "i/crlf" || c[1] == "i/mixed") print $2 }') # eol=crlf у атрибутах означає «цьому файлу CRLF призначено навмисно» # (.gitattributes: *.ps1). Такий файл у робочій копії з CRLF — норма. wt=$(printf '%s\n' "$list" | awk -F'\t' ' { split($1, c, " ") if ((c[2] == "w/crlf" || c[2] == "w/mixed") && $1 !~ /eol=crlf/) print $2 }') rc=0 if [ -n "$idx" ]; then echo "CRLF в ІНДЕКСІ — це поїде всім і зупинить накат міграцій:" printf '%s\n' "$idx" | sed 's/^/ /' echo " полагодити: git add --renormalize . && git commit" rc=1 fi if [ -n "$wt" ]; then n=$(printf '%s\n' "$wt" | wc -l | tr -d ' ') if [ "$STRICT" = "1" ]; then echo "CRLF у РОБОЧІЙ КОПІЇ ($n): у свіжому клоні на Linux такого бути не може." printf '%s\n' "$wt" | sed 's/^/ /' rc=1 else echo "увага: CRLF у робочій копії ($n файлів) — в індексі при цьому LF." echo " саме через це gofmt може показувати неформатованими файли," echo " яких ніхто не чіпав, а генератори — переписувати цілі файли." printf '%s\n' "$wt" | sed 's/^/ /' echo " полагодити: git config core.autocrlf false" echo " git rm --cached -r . && git reset --hard" fi fi if [ "$rc" = "0" ] && [ -z "$wt" ]; then echo "закінчення рядків у порядку" fi exit "$rc"