Hooks
Git-krokar är körbara skript i .git/hooks/ som körs vid specifika tidpunkter under git-åtgärder. Pitmaster identifierar och anropar krokar med hjälp av PHPs processkontroll (proc_open).
Krokar körs som standard
Repositoryåtgärder kör automatiskt de hooks som anges under Hooks Pitmaster körs. Om du vill inaktivera dem för ett repository-handtag skickar du med alternativ när du öppnar det:
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() och Pitmaster::clone() accepterar samma alternativ. För att köra en krok krävs proc_open(); på värdar där det är inaktiverat öppnar du arkiv med ['hooks' => false]. CLI öppnar alltid arkivet med krokar aktiverade.
Pitmaster letar endast efter krokar i <gitDir>/hooks. Den ignorerar core.hooksPath, och i ett länkat arbetsträd letar den i .git/worktrees/<name>/hooks, så de delade skripten i .git/hooks körs inte där (#12).
HookRunner, som beskrivs nedan, ignorerar dessa alternativ: om den anropas direkt körs kroken alltid.
HookRunner
use Pitmaster\Hooks\HookRunner;
$hooks = new HookRunner($repo->gitDir());
Kontrollera om en krok finns
if ($hooks->exists('pre-commit')) {
echo "pre-commit hook is installed\n";
}
En krok finns om filen finns på .git/hooks/<name> och är körbar.
Kör en krok
$result = $hooks->run('pre-commit');
echo $result['exitCode']; // 0 = success
echo $result['stdout']; // Hook's standard output
echo $result['stderr']; // Hook's standard error
Med argument
$result = $hooks->run('commit-msg', ['/path/to/COMMIT_EDITMSG']);
Med stdin
$result = $hooks->run('pre-push', ['origin', 'https://github.com/user/repo.git'], $stdinData);
Kroken pre-push tar emot ref-information via stdin.
Kontrollera om körningen lyckades
if ($hooks->runAndCheck('pre-commit')) {
// Hook passed (exit code 0), proceed with commit
} else {
// Hook rejected the operation
}
runAndCheck() är en praktisk metod som kör kroken och returnerar true om avslutningskoden är 0. Om kroken inte finns returnerar den true (ingen krok innebär ingen invändning).
Lista installerade krokar
$installed = $hooks->listHooks();
// ['pre-commit', 'commit-msg', 'post-checkout']
Listar alla körbara filer i .git/hooks/ (exkluderar filer av typen .sample).
run() returnerar avslutningskod 0 med tom utdata om kroken saknas eller inte är körbar. Om processen inte kan startas returnerar den avslutningskod 1 och skriver Failed to start hook till stderr.
Installera en krok
$hooks->install('pre-commit', "#!/bin/bash\nphp vendor/bin/phpcs --standard=PSR12 .\n");
Skriver skriptinnehållet till .git/hooks/<name> och anger körbehörighet (chmod 0755).
// 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);
Krokar som Pitmaster kör
HookRunner kan köra valfri krok med namn. Repository kör automatiskt följande:
| Krok | Körs av | Argument | Kan avbryta? |
|---|---|---|---|
pre-commit |
commit() |
inga | Ja (avslutningskod som inte är noll) |
prepare-commit-msg |
commit() |
meddelandefil, sedan message (eller merge när en sammanslagning slutförs) |
Ja |
commit-msg |
commit() |
meddelandefil (.git/COMMIT_EDITMSG); ändringar i filen används |
Ja (avslutningskod som inte är noll) |
post-commit |
commit() |
inga | Nej (endast information) |
pre-rebase |
rebase() |
uppströmsrevisionen | Ja |
post-checkout |
checkout() |
gammalt HEAD, nytt HEAD, 1 |
Nej (endast information) |
post-merge |
merge(), mergeOctopus(), mergeContinue() |
0 |
Nej (endast information) |
pre-push |
push() och dess varianter |
fjärrnamn, URL; ref-rader via stdin | Ja (avslutningskod som inte är noll) |
Om en krok misslyckas kastar operationen RuntimeException('<name> hook failed'); krokens utdata inkluderas inte. Commit-krokar körs endast från commit(): merge-commits som skapas av merge() kör dem inte. post-checkout körs inte för addWorktree(), reset() eller restore().
Krokar på serversidan (pre-receive, update, post-receive, post-update), pre-auto-gc och post-rewrite körs aldrig automatiskt.
Krokens miljö
När Pitmaster kör en krok skickar den med följande miljö:
$env = [
'GIT_DIR' => $this->gitDir,
'GIT_WORK_TREE' => dirname($this->gitDir),
];
Detta är de enda variabler som kroken får: PATH, HOME och alla andra variabler i processen PHP skickas inte vidare (#13). Använd absoluta sökvägar i krokskript eller ange PATH i skriptet; en shebang med #!/usr/bin/env php hittar bara tolkar i systemets standardsökväg.
Kroken körs i dirname($gitDir), vilket är arbetskatalogen för en vanlig .git-katalog.
Format för krokskript
Krokar kan skrivas i valfritt språk. Den första raden måste vara en shebang:
#!/bin/bash
# Bash hook
#!/usr/bin/env php
<?php
// PHP hook
#!/usr/bin/env python3
# Python hook
Exempel: pre-commit med Pitmaster
commit() kör redan pre-commit, prepare-commit-msg, commit-msg och post-commit, så programkoden behöver bara hantera felet:
try {
$commitId = $repo->commit('Add feature');
} catch (\RuntimeException $e) {
echo $e->getMessage(); // "pre-commit hook failed"
}
Anropa HookRunner själv endast med ett handtag som öppnats med ['hooks' => false] eller för krokar som Pitmaster inte kör.
Exempel på krokar
Git initierar arkiv med .sample-krokfiler; Pitmaster::init() skapar en tom hooks/-katalog. Pitmasters listHooks() utesluter .sample-filer:
.git/hooks/
pre-commit.sample (excluded from listHooks)
commit-msg.sample (excluded from listHooks)
pre-commit (included - installed by user)