Как вызвать скрипт, поддерживаемый в репо во время предварительного получения - PullRequest
0 голосов
/ 24 декабря 2018

Предположим, у меня есть скрипт юнит-теста, поддерживаемый моим git.Я хотел бы создать ловушку предварительного получения, чтобы вызвать этот юнит-тест.Однако предварительный прием должен быть установлен на стороне сервера.В моем репозитории структура каталогов выглядит совершенно иначе, чем в моем рабочем дереве.Как мне вызвать этот скрипт модульного теста?

Спасибо

ОБНОВЛЕНИЕ:

По сути, тестовый скрипт должен выполняться внутри рабочего дерева.В настоящее время моя работа заключается в том, чтобы сделать «git clone» во временном каталоге и сбросить HEAD.Тем не менее, этот подход не работает с более высокой версией GIT.Потому что не разрешено обновление ссылок в карантинной среде .Поэтому я все еще ищу жизненно важное решение.

1 Ответ

0 голосов
/ 24 декабря 2018

Чтобы интерпретатор команд (например, bash или perl) мог интерпретировать файл, полный команд, вы должны сначала написать файл, полный команд.

Объект внутри репозитория Git не является файлом,это просто объект, идентифицируемый по хеш-идентификатору.Более конкретно, если какой-то коммит с (скажем) хеш-идентификатором $C (коммит) содержит некоторый объект BLOB-объекта с хэш-идентификатором $B (блоб), вы должны указать Git extract blob $Bтекстовый файл где-то в файловой системе.Затем вы можете указать интерпретатору команды интерпретировать файл.

Обратите внимание, что идентификатор хеша $C не отображался выше.Он вступает в игру только тогда, когда вы не знаете хэш-идентификатор $B объекта BLOB-объекта.Если вы do знаете хэш-идентификатор коммита, а do знаете путь в commit $C, в котором указан объект BLOB-объекта $B, выможно использовать $C плюс путь к имени, чтобы найти $B:

B=$(git rev-parse $C:path/to/file.ext) || ... do something ...

rev-parse распечатает хэш-идентификатор blob $B или выведет сообщение об ошибке в stderr и выйдетненулевой, так что предложение || срабатывает.Обратите внимание, что $C может даже быть определенной веткой или именем тега для указания коммита, идентифицируемого этой веткой или тегом:

$ git rev-parse refs/tags/v2.18.0:t/test-lib.sh
28315706be709d28c85785e389b381a8617337e3

, но:

$ git rev-parse refs/tags/v2.18.0:t/nonexistent.sh
refs/tags/v2.18.0:t/nonexistent.sh
fatal: Path 't/nonexistent.sh' does not exist in 'refs/tags/v2.18.0'

refs/tags/v2.18.0:t/nonexistent.sh являетсястандартный вывод, в то время как fatal: ... является стандартным выводом ошибки, поэтому с B=$(...) мы получаем:

$ B=$(git rev-parse refs/tags/v2.18.0:t/nonexistent.sh)
fatal: Path 't/nonexistent.sh' does not exist in 'refs/tags/v2.18.0'
$ echo $?
128
$ echo $B
refs/tags/v2.18.0:t/nonexistent.sh

Вместо или в дополнение к rev-parse вы можете использовать git cat-file -p для печати содержимое этого большого двоичного объекта, либо по его необработанному хеш-идентификатору, либо по имени:

$ B=$(git rev-parse refs/tags/v2.18.0:t/test-lib.sh)
$ git cat-file -p $B | head
# Test framework for git.  See t/README for usage.
#
# Copyright (c) 2005 Junio C Hamano
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,

или:

$ git cat-file -p refs/tags/v2.18.0:t/test-lib.sh | head -1
# Test framework for git.  See t/README for usage.

При желании вы можете проверитьдерево любого данного коммита (например, $B или refs/tags/v2.18.0) с использованием git ls-tree.Используйте -r, чтобы создать рекурсивный список.Результат может быть довольно долгим;Вот часть вывода для v2.18.0:

$ git ls-tree -r refs/tags/v2.18.0
...
100644 blob 939d6870ecd7cfbc62f9fa3fb867e5c7362ed9bd    submodule.c
100644 blob 7856b8a0b3d676cde20095f69a4d000d8cf38615    submodule.h
100644 blob 5261e8cf499006c1d84fc42a3e96e4dee7f09ba1    symlinks.c
100644 blob 3bd959ae523cff7fe3a29f1abb92019b6d10515f    t/.gitattributes
100644 blob 4e731dc1e3bef53903f030ee7c63fe7ef7324cb1    t/.gitignore
...
100644 blob ac22ccbd3ee9f03a3b38249ac8efdbe96b5da2cd    t/test-binary-2.png
100644 blob 2b2181dca09089ed36d10ee8f6f67eedda8cf352    t/test-lib-functions.sh
100644 blob 28315706be709d28c85785e389b381a8617337e3    t/test-lib.sh
100755 blob 46bf6184798442560ad3ae7f68a7972680c5f8eb    t/test-terminal.perl
100644 blob d4ae6676d159599468de235bcf10a672cb452592    t/valgrind/.gitignore
100644 blob 0a6724fcc45eed89d612b0e641fd3fe6d4231fcb    t/valgrind/default.supp
100755 blob 669ebaf68be006ee53911f02da72e56cb5a100f0    t/valgrind/valgrind.sh
100644 blob 3d37c1bd251c5f8c5eb06ede72ab57b323888709    tag.c
100644 blob d469534e82a87b651abe752469d0547c2b560e10    tag.h
100644 blob 3467705e9b0e14a0230473186079e83a582e4345    tar.h
100644 blob 139ecd97f8eb88b597aab50c2eb2b171a11ef3ef    tempfile.c

Это должно дать вам достаточно строительных блоков, чтобы получить ответ на свой вопрос:

Я хотел бы создатьловушка предварительного получения для вызова [a] unit-test.

Итак, на сервере вам необходим скрипт.Этот сценарий отделен от хранилища (в .git/hooks/pre-receive есть копия сценария - принимающее хранилище обычно --bare, так что у него вообще нет рабочего дерева, так что идея связыванияк рабочему дереву копия сценария не является стартовой).

Однако предварительный прием должен быть установлен на стороне сервера.

Исправить.

В моем хранилище структура каталогов выглядит совершенно иначе, чем в моем рабочем дереве.

Это совершенно не имеет значения.На сервере нет вашего рабочего дерева;сервер является Git-репозиторием, вероятно, --bare и, следовательно, с нет рабочим деревом.

Как я могу вызвать этот скрипт модульного теста?

Во-первых, найдите коммит или коммиты, которые вы хотите протестировать, возможно, используя стандартный ввод ловушки предварительного получения.Хук предварительного приема получает на свой стандартный ввод список строк.Каждая строка имеет формат:

<old-value> SP <new-value> SP <ref-name> LF

, как описано в документации Githooks .<ref-name> всегда является полным ссылочным именем, поэтому оно имеет форму refs/tags/..., когда push-запрос запрашивает у сервера создание или обновление tag name, refs/heads/..., когда push-запрос запрашивает, чтобыСервер создает или обновляет имя branch и некоторую другую форму для любого другого запроса.Помните, что одна операция git push может сделать несколько запросов, поэтому вам нужно сканировать каждую строку для каждого справочного обновления.

Ровно одно из старого или нового хеш-значения в каждой строке может состоять из всех нулей.Это специальный нулевой хеш .Если старый хэш равен нулю, запрос должен создать новую ссылку .Если новый хэш равен нулю, запрос должен удалить существующую ссылку .В противном случае запрос обновить существующую ссылку .Старый хэш исходит от вашего собственного Git, а не от запрашивающего Git, поэтому эта часть вполне заслуживает доверия.

Прочитав все строки ввода, обнаружил все запросы и выяснил, какие из них фиксируют (s) чтобы проверить, ваша работа теперь состоит в том, чтобы найти тест (ы), которые вы хотите выполнить, и запустить их.Для каждого такого теста извлеките его в реальный файл и запустите его, однако это должно быть сделано в вашей тестовой среде.

Используйте результат (ы) ваших тестов, если таковые имеются, чтобы сообщитьваш крюк предварительного получения относительно того, разрешать ли прием получать или возражать против всего толчка.Если вы возражаете против push, вся операция отменяется.

Любые сообщения, которые вы выводите на stdout или stderr, будут связаны с тем, кто делает git push, где им будет предшествовать строка remote: toуказать, что эти сообщения приходят из вашего кода, а не из самого Git.Используйте эти строки, чтобы сообщить кому-то , почему их толчок отклонен и как это исправить, в противном случае вы будете сильно путаться.

Замечания по поиску коммитов для тестирования

Некоторые системы тестируют только final commit, который идет в какую-то конкретную ветку или ветви.Это более простой метод, поскольку вы можете просто использовать новый хэш-идентификатор в качестве своего коммита.

Другие тестовые системы тестируют каждый новый коммит , который идет в какую-то конкретную ветку или ветви.Для этого используйте git rev-list, что очень похоже на git log, за исключением того, что его вывод предназначен для чтения компьютерной программой.Вместо того, чтобы печатать сообщение журнала для каждого коммита, он печатает хэш-идентификатор каждого коммита.

Следовательно, если push-запрос говорит, например:

0123456789012345678901234567890123456789 aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd refs/heads/develop

, вы знаете, что pushзапрос на установку refs/heads/develop для хеш-идентификатора aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd, когда он в данный момент 0123456789012345678901234567890123456789.Таким образом, коммиты, которые будут вновь доступны через имя ветви develop, в точности совпадают с напечатанными:

git rev-list 0123456789012345678901234567890123456789..aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd

, поэтому запустите эту команду и соберите ее вывод (список хеш-идентификаторов коммитов)), чтобы найти коммиты для тестирования.

Обратите внимание, что если push удаляет некоторые коммиты, они будут перечислены в обратной операции:

git rev-list aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd..0123456789012345678901234567890123456789

Вы можете использовать это для обнаружения принудительных операций push, которые удаляют коммиты из ветви.

...