Ваше существующее решение, вероятно, достаточно.Хотя это не на 100% правильно: вот оставшиеся проблемы, все из которых являются незначительными, которые вы можете исправить позже (если когда-либо) на досуге:
Вам нужны только git diff ... --staged
(или --cached
), поскольку Git будет фиксировать все файлы в области index / staging-области, а git diff
сравнивает это с тем, что находится в коммите HEAD
, и сообщает вам, что там происходит.Если копия файла в индексе отличается от копии файла в HEAD
, вам следует изучить копию индекса.
Технически было бы лучше использовать git diff-index --cached
здесь, чтобы не подчиняться какой-либо конфигурации пользователя git diff
.Таким образом, git diff-index
- это команда plumbing в Git, что означает, что она предназначена для использования из других компьютерных программ: она выполняется полностью предсказуемым образом, основываясь только на аргументах, а не на любых настройках git config
,Но если вы делаете это для себя, и вы настраиваете git diff
таким образом, что это нарушает ваше собственное использование git diff
, то это ваша собственная ошибка.: -)
Вы также можете использовать --diff-filter
для исключения удаленных файлов.В противном случае ваша программа проверки всегда удастся удалить (так как iconv
не сможет прочитать удаленный файл).
Наиболее важно: iconv
будет считывать файл из работа дерево .Как я отметил в первом пункте, Git собирается зафиксировать то, что staged , а не то, что находится в рабочем дереве.
В качестве примера, который может илиможет быть невозможным изнутри TortoiseGit - подумайте, что произойдет, если вы сделаете следующее:
$ git checkout master
$ printf '\300\300\300' > badfile # put bad non-UTF-8 crud into file
$ git add badfile # copy file into index
$ echo 'good data' > badfile # replace work-tree contents
$ git commit
Этот коммит будет фиксировать плохое содержимое - три байта \300
безсимвол новой строки - который находится в индексе, но ваш хук перед фиксацией будет запускать iconv -f utf-8 -t utf-16
над содержимым файла good , читая good data
, что, конечно, хорошо.
Чтобы исправить это, ваш фильтр предварительной фиксации должен извлечь данные из индекса для каждого файла, который должен быть зафиксирован.Как вы поступите так, зависит от вас.Самый простой (но, возможно, самый медленный) метод - просто извлечь все содержимое индекса во временную рабочую область, используя git checkout-index
.Лучшим методом может быть преобразование каждого имени пути в индексной области (in-staging-area) в допустимый спецификатор индекса (то есть path/to/file
становится :path/to/file
) и использование git cat-file -p $specifier | iconv ...
для сканирования каждого.Но все это будет довольно неэффективно, особенно в Windows.Для эффективности вы можете написать скрипт на Python, который использует git cat-file --batch
, чтобы извлечь их все за один проход, и выполнить проверку формата там.