Атрибут git с использованием фильтра smudge/clean для обработки файлов.cpp с помощью сценария оболочки, который не находит имя файла
Я хотел настроить форматирование кода для всех файлов.cpp до того, как они будут переданы в git.
Для этого я создал небольшой скрипт (с именем codeformat) (также попытался заменить%f на $1)
#! /bin/bash
clang-format -style=file %f | diff %f -**
if [ $? -ne 0 ]; then
echo "ERROR: codeformat not correct"
exit 1
fi
установил git config и обновил.gitattributes с помощью *.cpp filter=codeformat,
git config --global filter.codeformat.clean codeformat
git config --global filter.codeformat.smudge codeformat
похоже, что скрипт запускается, но не получает имя файла. Почему это?
3 ответа
У тебя есть %f
директива не в том месте.
Как показано в документации по gitattributes (найдите %f
):
Последовательность "%f" в командной строке фильтра заменяется именем файла, над которым работает фильтр. Фильтр может использовать это в подстановке ключевых слов. Например:
[filter "p4"] clean = git-p4-filter --clean %f smudge = git-p4-filter --smudge %f
Следовательно, чтобы получить путь к файлу, вам нужно установить, например, filter.codeformat.clean
в codeformat %f
,
На этом этапе вам также потребуется изменить скрипт bash, поскольку его синтаксис для подстановки аргументов действительно $1
, Тем не менее, прочитайте следующий абзац из документации по gitattributes:
Обратите внимание, что "%f" - это имя пути, над которым вы работаете. В зависимости от фильтруемой версии, соответствующий файл на диске может не существовать или иметь различное содержимое. Таким образом, команды smudge и clean не должны пытаться получить доступ к файлу на диске, а действуют только как фильтры для содержимого, предоставленного им при стандартном вводе.
Акцент здесь мой, но это говорит о том, что вы не можете просто открыть файл на диске и прочитать его. Вы должны фильтровать только стандартный ввод, обеспечивая стандартный вывод.
( Как выясняется, формат clang предназначен именно для этого. Различия, однако, нет.)
Изменить, чтобы добавить рабочий пример:
$ cat ~/scripts/dotest
#! /bin/sh
echo "dotest run with $# arguments:" >>/tmp/dotest_log
for i do
printf '%s\n' "$i"
done >>/tmp/dotest_log
cat
$ which dotest
[path edited]/scripts/dotest
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[filter "testfilter"]
clean = dotest %f
smudge = dotest %f
$ cat .gitattributes
*.test filter=testfilter
$ echo 'bar.test' > bar.test
$ git add bar.test
$ cat /tmp/dotest_log
dotest run with 1 arguments:
bar.test
%f
интерпретируется git
и должен быть в gitconfig
, В сценарии оболочки используйте $1
:
git config --global filter.codeformat.clean 'codeformat %f'
git config --global filter.codeformat.smudge 'codeformat %f'
#! /bin/bash
clang-format -style=file $1 | diff $1 -**
if [ $? -ne 0 ]; then
echo "ERROR: codeformat not correct"
exit 1
fi
Это означает, что я никогда не могу получить имя файла?, я попробовал%f с самим git config и изменил скрипт на использование $1, но он не получает имя файла.
cat ~/.gitconfig
[filter "codeformat"]
clean = codeformat %f
smudge = codeformat %f
cat .gitattributes
#clang code style format
*.cpp filter=codeformat
cat codeformat
#! /bin/bash
clang-format -i -style=file $1 -
echo "file/path accessed is _____ $1 ____" > log_output 2>&1
git add src/sample.cpp
cat log_output
file/path accessed is _____ ____
та же команда (ниже), если я запускаю в командной строке, работает хорошо,
clang-format -i -style=file src/sample.cpp
С git add он не может получить имя файла и, следовательно, другую ошибку с ошибкой: не может использовать -i при чтении из стандартного ввода.
на этот раз, я удалил команду diff, использовал -i для прямой замены исходного файла "