Pereiti prie turinio

Įskiepiai

Git kabliai yra vykdomi scenarijai .git/hooks/ aplinkoje, paleidžiami tam tikrais git operacijų momentais. Pitmaster aptinka ir iškviečia kablius naudodama PHP procesų valdymą (proc_open).

Kabliai vykdomi pagal numatytuosius nustatymus

Saugyklos operacijos automatiškai vykdo Kabliai Pitmaster nurodytus kablius. Norėdami juos išjungti saugyklos deskriptoriui, perduokite parinktis jį atidarydami:

PHP
use Pitmaster\Pitmaster;

// Skip .git/hooks scripts for this handle
$repo = Pitmaster::open('/path/to/project', ['hooks' => false]);

// Start no processes at all: hooks, the fsmonitor hook, clone/fetch/push, and SSH are disabled
$repo = Pitmaster::open('/path/to/project', Pitmaster::processFreeOptions());

$repo->hooksEnabled();      // false
$repo->processesEnabled();  // false for the second handle

Pitmaster::init() ir Pitmaster::clone() priima tas pačias parinktis. Kabliui vykdyti reikia proc_open(); aplinkose, kuriose jis išjungtas, atidarykite saugyklas su ['hooks' => false]. CLI visada atidaro saugyklą su įjungtais kabliais.

Pitmaster kablių ieško tik <gitDir>/hooks. Jis nepaiso core.hooksPath, o susietame darbiniame medyje ieško .git/worktrees/<name>/hooks, todėl bendrinami .git/hooks scenarijai ten nevykdomi (#12).

HookRunner, aprašytas toliau, šių parinkčių nepaiso: iškvietus jį tiesiogiai, kablys visada vykdomas.

HookRunner

PHP
use Pitmaster\Hooks\HookRunner;

$hooks = new HookRunner($repo->gitDir());

Tikrinimas, ar kablys yra

PHP
if ($hooks->exists('pre-commit')) {
    echo "pre-commit hook is installed\n";
}

Kablys laikomas esančiu, jei failas yra .git/hooks/<name> ir yra vykdomas.

Kabliuko vykdymas

PHP
$result = $hooks->run('pre-commit');

echo $result['exitCode'];  // 0 = success
echo $result['stdout'];    // Hook's standard output
echo $result['stderr'];    // Hook's standard error

Su argumentais

PHP
$result = $hooks->run('commit-msg', ['/path/to/COMMIT_EDITMSG']);

Su stdin

PHP
$result = $hooks->run('pre-push', ['origin', 'https://github.com/user/repo.git'], $stdinData);

pre-push kabliui informacija apie nuorodas perduodama per stdin.

Sėkmės tikrinimas

PHP
if ($hooks->runAndCheck('pre-commit')) {
    // Hook passed (exit code 0), proceed with commit
} else {
    // Hook rejected the operation
}

runAndCheck() yra patogumo funkcija: ji vykdo kablį ir grąžina true, jei išėjimo kodas yra 0. Jei kablio nėra, grąžinama true (kablio nebuvimas reiškia, kad nėra prieštaravimų).

Įdiegtų kablių sąrašas

PHP
$installed = $hooks->listHooks();
// ['pre-commit', 'commit-msg', 'post-checkout']

Išvardija visus vykdomus failus aplanke .git/hooks/ (neįtraukia .sample failų).

run(), jei kablio nėra arba jis nevykdomas, grąžina išėjimo kodą 0 ir tuščią išvestį. Jei proceso nepavyksta paleisti, grąžinamas išėjimo kodas 1, o Failed to start hook pateikiamas stderr.

Kabliuko diegimas

PHP
$hooks->install('pre-commit', "#!/bin/bash\nphp vendor/bin/phpcs --standard=PSR12 .\n");

Įrašo scenarijaus turinį į .git/hooks/<name> ir nustato vykdymo leidimą (chmod 0755).

PHP
// Install a PHP hook
$hooks->install('pre-commit', <<<'HOOK'
#!/usr/bin/env php
<?php
// Run static analysis before commit
$output = [];
$returnCode = 0;
exec('php vendor/bin/phpstan analyse --no-progress 2>&1', $output, $returnCode);

if ($returnCode !== 0) {
    echo "PHPStan found errors:\n";
    echo implode("\n", $output) . "\n";
    exit(1);
}
HOOK);

Kabliai, kuriuos vykdo Pitmaster

HookRunner gali vykdyti bet kurį kablį pagal pavadinimą. Repository automatiškai vykdo šiuos:

Kablys Vykdo Argumentai Gali nutraukti?
pre-commit commit() nėra Taip (ne nulinis išėjimo kodas)
prepare-commit-msg commit() pranešimo failas, tada message (arba merge užbaigiant sujungimą) Taip
commit-msg commit() pranešimo failas (.git/COMMIT_EDITMSG); failo pakeitimai naudojami Taip (ne nulinis išėjimo kodas)
post-commit commit() nėra Ne (informacinis)
pre-rebase rebase() pirminės šakos revizija Taip
post-checkout checkout() senasis HEAD, naujasis HEAD, 1 Ne (informacinis)
post-merge merge(), mergeOctopus(), mergeContinue() 0 Ne (informacinis)
pre-push push() ir jo variantai nuotolinės saugyklos pavadinimas, URL; nuorodų eilutės per stdin Taip (ne nulinis išėjimo kodas)

Neveikiančio kablio vykdymas priverčia operaciją išmesti RuntimeException('<name> hook failed'); kablio išvestis neįtraukiama. Commit kabliai vykdomi tik iš commit(): sujungimo commit, sukurtas naudojant merge(), jų nevykdo. post-checkout nevykdomas su addWorktree(), reset() ar restore().

Serverio pusės kabliai (pre-receive, update, post-receive, post-update), pre-auto-gc ir post-rewrite niekada nevykdomi automatiškai.

Kablių aplinka

Kai Pitmaster vykdo kablį, perduodama ši aplinka:

PHP
$env = [
    'GIT_DIR' => $this->gitDir,
    'GIT_WORK_TREE' => dirname($this->gitDir),
];

Tai vieninteliai kabliui perduodami kintamieji: PATH, HOME ir visi kiti PHP proceso kintamieji neperduodami (#13). Kablių scenarijuose naudokite absoliučiuosius kelius arba scenarijaus viduje nustatykite PATH; #!/usr/bin/env php shebang randa interpretatorius tik numatytajame sistemos kelyje.

Kablys vykdomas dirname($gitDir) kataloge, kuris įprastos .git saugyklos atveju yra darbinis medis.

Kablių scenarijų formatas

Kablius galima rašyti bet kuria kalba. Pirmoji eilutė turi būti shebang:

Shell
#!/bin/bash
# Bash hook
PHP
#!/usr/bin/env php
<?php
// PHP hook
Python
#!/usr/bin/env python3
# Python hook

Pavyzdys: pre-commit su Pitmaster

commit() jau vykdo pre-commit, prepare-commit-msg, commit-msg ir post-commit, todėl programos kodui tereikia apdoroti nesėkmę:

PHP
try {
    $commitId = $repo->commit('Add feature');
} catch (\RuntimeException $e) {
    echo $e->getMessage(); // "pre-commit hook failed"
}

HookRunner kvieskite patys tik tada, kai deskriptorius atidarytas su ['hooks' => false], arba kai vykdomi kabliai, kurių Pitmaster nevykdo.

Kablių pavyzdžiai

Git inicijuoja saugyklas su .sample kablių failais; Pitmaster::init() sukuria tuščią hooks/ katalogą. Pitmaster listHooks() neįtraukia .sample failų:

Kodas
.git/hooks/
  pre-commit.sample       (excluded from listHooks)
  commit-msg.sample       (excluded from listHooks)
  pre-commit              (included - installed by user)