Git вызывает внутреннюю функцию execute_commands
для обработки команд, отправленных клиентом git-receive-pack
.
Независимо от того, какие ссылки отправляет пользователь, Git создает или обновляет соответствующие ссылки, если у пользователя есть разрешение на запись.
Участник, у которого нет прав на запись, не может отправлять данные в репозиторий напрямую.
Таким образом, участник должен записывать коммиты в альтернативное место и отправляет запрос на извлечение по электронной почте или другими способами.
Мы звоним этот рабочий процесс как распределенный рабочий процесс.
Было бы удобнее работать в централизованном рабочем процессе, подобно тому, что Gerrit предлагал для некоторых случаев.
Например, пользователь с правами только для чтения, который не может отправлять данные в ветку напрямую, может запустить следующий git push
(man) sup> для отправки коммитов на псевдоссылку (имеет префикс refs/for/
, а не refs/heads/
) для создания обзора кода.
git push origin \
HEAD:refs/for/<branch-name>/<session>
<branch-name>
в приведенном выше примере может быть таким же простым, как master
, или более сложным именем ветки, например foo/bar
.
<session>
в приведенной выше команде примера может быть именем локальной ветки на стороне клиента, например my/topic
.
Мы не можем элегантно реализовать централизованный рабочий процесс, используя pre-receive
+ post-receive
, потому что Git вызовет внутреннюю функцию execute_commands
для создания ссылок (даже специальной псевдоссылки) между этими двумя хуками.
Несмотря на то, что мы можем удалить временно созданную псевдоссылку через хук post-receive
наличие временной ссылки небезопасно для одновременных push-уведомлений.
Итак, добавьте фильтр и новый обработчик для поддержки такого рабочего процесса.
Фильтр будет проверять префикс имени ссылки, и если команда имеет специальное имя ссылки, фильтр включит определенное поле (run_proc_receive
) для команды.
Команды с включенным этим полем будут выполняться новый обработчик (хук с именем proc-receive
) вместо внутренней функции execute_commands
.
Эту команду proc-receive
можно использовать для создания запросов на вытягивание или отправки электронных писем для проверки кода.
Предложенный Junio, этот хук proc-receive
читает команды, push-опции (необязательно) и отправляет результат, используя протокол в формате pkt-line
.
В следующем примере буква S
означает receive-pack
, а буква H
— хук. .
# Version and features negotiation.
S: PKT-LINE(version=1\0push-options atomic...)
S: flush-pkt
H: PKT-LINE(version=1\0push-options...)
H: flush-pkt
# Send commands from server to the hook.
S: PKT-LINE(<old-oid> <new-oid> <ref>)
S: ... ...
S: flush-pkt
# Send push-options only if the 'push-options' feature is enabled.
S: PKT-LINE(push-option)
S: ... ...
S: flush-pkt
# Receive result from the hook.
# OK, run this command successfully.
H: PKT-LINE(ok <ref>)
# NO, I reject it.
H: PKT-LINE(ng <ref> <reason>)
# Fall through, let 'receive-pack' to execute it.
H: PKT-LINE(ok <ref>)
H: PKT-LINE(option fall-through)
# OK, but has an alternate reference. The alternate reference name
# and other status can be given in options
H: PKT-LINE(ok <ref>)
H: PKT-LINE(option refname <refname>)
H: PKT-LINE(option old-oid <old-oid>)
H: PKT-LINE(option new-oid <new-oid>)
H: PKT-LINE(option forced-update)
H: ... ...
H: flush-pkt
После получения команды хук выполнит команду и может создать/обновить другую ссылку.
Например, команда для псевдоссылки refs/for/master/topic
может создать/обновить другую ссылку, такую как refs/pull/123/head
.
Имя альтернативной ссылки и другой статус задаются в строках параметров.
Список команд, возвращенных proc-receive
, заменит соответствующие команды, отправленные пользователем receive-pack
, а receive-pack
продолжит выполнение функции "execute_commands
и других подпрограмм.
Наконец, результат выполнения этих команд будет сообщен конечному пользователю.
Функция отчетов от receive-pack
до send-pack
будет расширена в последнем коммите точно так же, как хук proc-receive
сообщает receive-pack
.