Documentation
¶
Overview ¶
Package gitenv запускает git так, чтобы он работал с ТЕМ репозиторием, который назвал вызывающий, а не с тем, который назвали за него переменные окружения.
Предмет ¶
git определяет репозиторий не только по рабочему каталогу. Если в окружении есть `GIT_DIR`, она **сильнее** рабочего каталога: `cmd.Dir = <свой каталог>` перестаёт что-либо значить, и команда работает с чужим репозиторием.
В этом дереве полтора десятка проб заводят синтетический репозиторий во временном каталоге (`git init` + `git add -A`), задавая рабочий каталог и полагаясь на то, что git определит репозиторий по нему. Допущение неверно ровно тогда, когда `go test` запущен из хука git: `git push` выставляет `GIT_DIR`, и его наследует всё, что хук запускает.
Цена измерена на дереве `release/console`, одни и те же пакеты (`./internal/repohygiene/... ./tools/...`):
индекс рабочей копии после упавших пакетов без GIT_DIR 6994 записи — цел 0 с GIT_DIR 3 записи 119
Вместе с индексом в конфигурацию рабочей копии уезжали `user.name`, `user.email` и `core.bare=true` — записи фикстур, выглядевшие как чужое вмешательство в клон.
Почему следствие тихое ¶
Падают не виновные пробы, а те, что читают состав дерева через `git ls-files` ([treecorpus]): они видят схлопнутый индекс и честно сообщают «прочитано ноль». Виновник не назван ни одной строкой вывода, а «ноль находок» превращается в «ноль прочитанного» — тот самый класс, ради различения которого эти гейты и написаны.
Граница, а не пожелание ¶
Хук `scripts/hooks/pre-push` снимает те же переменные перед запуском проверок — это закрывает ТРИГГЕР. Пакет закрывает КЛАСС: любой другой запуск `go test` с выставленным `GIT_DIR` (из другого хука, из скрипта, из обёртки) повторил бы то же самое. Перечень переменных объявлен здесь один раз (Vars), и его совпадение с перечнем хука проверяется пробой — иначе получились бы два места об одном предмете, из которых верно одно.
Держится гейтом `internal/repohygiene` `TestGitCommandsRunWithScrubbedEnvironment`: прямой `exec.Command("git", …)` вне этого пакета — находка.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Command ¶
Command собирает вызов git с рабочим каталогом dir и окружением Env.
Пустой dir означает рабочий каталог процесса — законный случай для команд, которые спрашивают про репозиторий, из которого запущен прогон (например `rev-parse HEAD` в измерителе). Отсутствие каталога здесь представимо отдельно от значения: пустая строка не является путём.
Дополнить окружение (подпись фикстуры, локаль) можно только ДОПИСЫВАНИЕМ:
cmd := gitenv.Command(dir, "commit", "-m", "x") cmd.Env = append(cmd.Env, "GIT_AUTHOR_NAME=t")
Присваивание `cmd.Env = append(os.Environ(), …)` вернуло бы снятые переменные обратно — гейт `internal/repohygiene` это отдельно ловит.
func CommandContext ¶
CommandContext — то же, что Command, со сроком вызова.
Types ¶
This section is empty.