Как ссылаться на другие значения конфигурации в .gitconfig - PullRequest
0 голосов
/ 15 января 2019

TL; DR

Как мне указать .gitconfig значение конфигурации в другом значении конфигурации?

.gitconfig

[filter "myFilter"]
    foo = Hello world
    bar = echo $(git config filter.myFilter.foo)

Баш

$(git config filter.myFilter.bar)
# should print "Hello world"

Моя проблема

Я пытаюсь написать несколько smudge / clean фильтров (а-ля Может ли git автоматически переключаться между пробелами и табуляциями? ), чтобы при оформлении заказа размер табуляции был равен 4 пробелам, и совершить, они возвращаются к тому, что уже находится в репо.

Ответы SO предлагают это:

git config --global filter.tabspace.smudge 'unexpand --tabs=4'
git config --global filter.tabspace.clean 'expand --tabs=4'

Или эквивалентный .gitconfig файл:

[filter "tabspace"]
    smudge = 'unexpand --tabs=4'
    clean = 'expand --tabs=4'

Это прекрасно работает, если вы знаете, что все ваши удаленные репозитории используют вкладки. Я хочу обобщить это (и в процессе, узнать больше о git config), чтобы я мог установить значение, а значения в ~/.gitconfig сделают все остальное.


Желаемое поведение

Мой ~/.gitconfig выглядит как

#...

[filter "tabspace"]
    repoTabs = false
    repoTabSize = 4
    smudge = # TODO
    clean = # TODO

#...

Когда я клонирую репо, использующий табуляции или не 4 пробела, я запускаю

# for repos that use tabs
git config filter.tabspace.repoTabs true

# for repos that use 2 spaces
git config filter.tabspace.repoTabSize 2

, а затем создайте файл на .git/info/attributes, который выглядит как

*.js    filter=tabspace
*.jsx   filter=tabspace
*.ts    filter=tabspace
*.tsx   filter=tabspace
*.json  filter=tabspace

Частичное решение

Сценарии, которые я хочу использовать для smudge и clean, должны быть относительно простыми (я написал их по одной в каждой строке, в моем файле ~/.gitconfig вместо двух # TODO с):

# smudge
if [ `#filter.tabspace.repoTabs` == true ]; then
    expand --tabs=4
else
    unexpand --tabs=`#filter.tabspace.repoTabSize` | expand --tabs=4
fi

# clean
if [ `#filter.tabspace.repoTabs` == true ]; then
    unexpand --tabs=4
else
    unexpand --tabs=4 | expand --tabs=`#filter.tabspace.repoTabSize`
fi

Что я не могу понять для себя, так это как заставить значения filter.tabspace.repoTabs и filter.tabspace.repoTabSize работать в скрипте.

Мой метод тестирования - установить smudge = #my-script-here, а затем запустить

$(git config filter.tabspace.smudge)

, где #my-script-here - это что-то вроде echo $(git config filter.tabspace.repoTabSize) с десятками попыток заключить различные части значения в одинарные, двойные, двойные кавычки и обратные кавычки вместо $(). Все, что я пробовал, либо оценивает $(git config filter.tabspace.repoTabSize) буквально, либо не дает результата.

Я также пытался просто использовать repoTabSize, надеясь, что он просто вставит переменную scoped, но не повезло.


В качестве проверки работоспособности:

git config filter.tabspace.repoTabSize 2
echo $(git config filter.tabspace.repoTabSize)

# prints
2

Я также проверил, что передача значения в оператор if делает то, что мне нужно, предполагая, что git checkout и git commit передают файлы через значения filter.tabspace.smudge и filter.tabspace.clean соответственно.

echo -e '\t'foo | if [ true ]; then expand --tabs=4; fi

# prints (with 4 spaces):
    foo

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Это больше вопрос программирования оболочки, чем что-либо еще.

Обратите внимание, что git config --get возвращает вам код завершения, чтобы сказать, было ли что-то установлено:

$ git config --get branch.master.merge; echo $?
refs/heads/master
0
$ git config --get branch.master.marge; echo $?
1

Вы можете добавить --default <value>, но это победит код выхода:

$ git config --get --default simpson branch.master.marge; echo $?
simpson
0

Существует также git config --get -t <type> <name>, который преобразует фактическую настройку в правильное значение и выдает ее, либо выдает ошибку (в stderr) и завершается с ошибкой на основе предоставленного типа:

$ git config --get -t bool core.bare; echo $?
false
0
$ git config --get -t bool branch.master.merge; echo $?
fatal: bad numeric config value 'refs/heads/master' for 'branch.master.merge' in file .git/config: invalid unit
128

Таким образом, в сценарии оболочки вы можете просто проверить, установлено ли значение вообще как ваше решение, или использовать отдельное логическое значение при попытке:

#! /bin/sh
do_tabs=$(git config --get -t bool --default false filter.tabspace.repotabs) || exit
if $do_tabs; then
    tabsize=$(git config --get -t int --default 8 filter.tabspace.repotabsize) || exit
fi

или

#! /bin/sh
tabsize=$(git config --get -t int filter.tabspace.size)
case $? in
0) do_tabs=true;;
1) do_tabs=false;;
*) exit;;
esac

Теперь, так или иначе, у вас есть две переменные, которые фиксируют как желание («мы должны сделать эту вкладку?»), Так и, если $ do_tabs, фактический размер, так что теперь вы можете написать:

case "#1" in)
--smudge) is_smudge=true;;
--clean) is_smudge=false;;
*) echo "run with --smudge or --clean"; exit 1;;
esac

if $is_smudge; then
    if $do_tabs; then
        expand --$tabsize
    fi
else
    ...
fi

(заполните остальное очевидным образом). Результирующий скрипт может быть вызван с помощью:

[filter "tabspace"]
    smudge = script_name --smudge
    clean = script_name --clean

Аргумент ($1) определяет режим работы, и две настройки берутся из файла конфигурации, а сценарий читает stdin и записывает stdout по мере необходимости.

Я не пытался воспроизвести ваш полный код, так как здесь есть кое-что очень странное для меня:

раскрыть --tabs = 4 | раскрыть --tabs = [любое число здесь]

Программа unexpand заменит начальные пробелы соответствующими вкладками, при этом четыре пробела станут одной вкладкой, 8 - 2 и т. Д .; expand заменит некоторое количество пробелов. Если число --tabs= также равно 4, все это большой запрет. Но если --tabs= отличается, то для этого требуется файл, содержащий только пробелы, что, как вам кажется, соответствует всем файлам рабочего дерева, и изменяет количество пробелов, когда они приводят пространства. Это кажется странной вещью. Разве не имеет смысла помещать жесткие вкладки в файл на каждых 8 позициях, как это обычно ожидает остальная часть системы? Если это так, все вызовы --unexpand не должны иметь аргументов, и --expand также не может иметь аргументов, поскольку файлы в рабочем дереве всегда имеют только пробелы.

0 голосов
/ 15 января 2019

Это ужасно многословно, поэтому я все же хотел бы получить лучший ответ, но, используя eval и некоторые двойные кавычки, которых я избежал, я могу добиться того, чего хочу.

В моих сценариях частичного решения мне нужно было заменить:

`#filter.tabspace.repoTabs` -> $(eval "git config filter.tabspace.repoTabs")
`#filter.tabspace.repoTabSize` -> $(eval "git config filter.tabspace.repoTabSize")

Затем мне нужно было обернуть значение в двойные кавычки - что также означает экранирование двойных кавычек в выражениях eval.

Окончательный результат:

[filter "tabspace"]
    repoTabs = false
    repoTabSize = 4
    smudge = "if [ $(eval \"git config filter.tabspace.repoTabs\") == true ]; then expand --tabs=4; else unexpand --tabs=$(eval \"git config filter.tabspace.repoTabSize\") | expand --tabs=4; fi"
    clean = "if [ $(eval \"git config filter.tabspace.repoTabs\") == true ]; then unexpand --tabs=4; else unexpand --tabs=4 | expand --tabs=$(eval \"git config filter.tabspace.repoTabSize\"); fi"

Кроме того, ответы на вопрос SO, на который делается ссылка, не дали хорошего метода для принудительного запуска пятна. Этот ответ был намного лучше.

Предупреждение: не делайте этого, если у вас есть файлы, которые не зафиксированы.

rm .git/index
git checkout HEAD -- "$(git rev-parse --show-toplevel)"
...