Kancalar
Git kancaları, git işlemlerinin belirli aşamalarında çalışan, .git/hooks/ içindeki yürütülebilir betiklerdir. Pitmaster, kancaları PHP işlem denetimini (proc_open) kullanarak algılar ve çağırır.
Kancalar varsayılan olarak çalışır
Depo işlemleri, Kancalar Pitmaster çalıştırır altında listelenen kancaları otomatik olarak çalıştırır. Bir depo tanıtıcısı için bunları kapatmak üzere depoyu açarken seçenekleri iletin:
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() ve Pitmaster::clone() aynı seçenekleri kabul eder. Bir kancayı çalıştırmak için proc_open() gerekir; bunu devre dışı bırakan sistemlerde depoları ['hooks' => false] ile açın. CLI depoyu her zaman kancalar etkin olarak açar.
Pitmaster kancaları yalnızca <gitDir>/hooks içinde arar. core.hooksPath konumunu yok sayar; bağlantılı bir worktree'de ise .git/worktrees/<name>/hooks içinde arar, bu nedenle paylaşılan .git/hooks betikleri burada çalışmaz (#12).
Aşağıda açıklanan HookRunner bu seçenekleri yok sayar: doğrudan çağrıldığında kancayı her zaman çalıştırır.
HookRunner
use Pitmaster\Hooks\HookRunner;
$hooks = new HookRunner($repo->gitDir());
Kancanın mevcut olup olmadığını denetleme
if ($hooks->exists('pre-commit')) {
echo "pre-commit hook is installed\n";
}
.git/hooks/<name> konumunda dosya varsa ve yürütülebilir durumdaysa kanca mevcuttur.
Kanca çalıştırma
$result = $hooks->run('pre-commit');
echo $result['exitCode']; // 0 = success
echo $result['stdout']; // Hook's standard output
echo $result['stderr']; // Hook's standard error
Bağımsız değişkenlerle
$result = $hooks->run('commit-msg', ['/path/to/COMMIT_EDITMSG']);
Standart girdiyi kullanarak
$result = $hooks->run('pre-push', ['origin', 'https://github.com/user/repo.git'], $stdinData);
pre-push kancası, başvuru bilgilerini standart girdiden alır.
Başarıyı denetleme
if ($hooks->runAndCheck('pre-commit')) {
// Hook passed (exit code 0), proceed with commit
} else {
// Hook rejected the operation
}
runAndCheck(), kancayı çalıştıran ve çıkış kodu 0 ise true döndüren bir kolaylık yöntemidir. Kanca yoksa true döndürür (kanca yoksa itiraz da yoktur).
Kurulu kancaları listeleme
$installed = $hooks->listHooks();
// ['pre-commit', 'commit-msg', 'post-checkout']
.git/hooks/ konumundaki yürütülebilir tüm dosyaları listeler (.sample dosyaları hariç).
Eksik veya yürütülemeyen bir kanca için run(), boş çıktı ve 0 çıkış kodu döndürür. İşlem başlatılamazsa standart hata akışında Failed to start hook ile birlikte 1 çıkış kodu döndürür.
Kanca kurma
$hooks->install('pre-commit', "#!/bin/bash\nphp vendor/bin/phpcs --standard=PSR12 .\n");
Betik içeriğini .git/hooks/<name> konumuna yazar ve yürütme iznini ayarlar (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);
Pitmaster tarafından çalıştırılan kancalar
HookRunner, ada göre herhangi bir kancayı çalıştırabilir. Repository şu kancaları otomatik olarak çalıştırır:
| Kanca | Çalıştıran | Bağımsız değişkenler | İşlemi durdurabilir mi? |
|---|---|---|---|
pre-commit |
commit() |
yok | Evet (sıfır olmayan çıkış) |
prepare-commit-msg |
commit() |
ileti dosyası, ardından message (birleştirme tamamlanırken merge) |
Evet |
commit-msg |
commit() |
ileti dosyası (.git/COMMIT_EDITMSG); dosyadaki düzenlemeler kullanılır |
Evet (sıfır olmayan çıkış) |
post-commit |
commit() |
yok | Hayır (bilgilendirme amaçlı) |
pre-rebase |
rebase() |
üst akış revizyonu | Evet |
post-checkout |
checkout() |
eski HEAD, yeni HEAD, 1 |
Hayır (bilgilendirme amaçlı) |
post-merge |
merge(), mergeOctopus(), mergeContinue() |
0 |
Hayır (bilgilendirme amaçlı) |
pre-push |
push() ve türevleri |
uzak depo adı, URL; başvuru satırları standart girdide | Evet (sıfır olmayan çıkış) |
Başarısız bir kanca işlemin RuntimeException('<name> hook failed') hatasını fırlatmasına neden olur; kancanın çıktısı eklenmez. Commit kancaları yalnızca commit() üzerinden çalışır: merge() tarafından oluşturulan birleştirme commit'leri bunları çalıştırmaz. post-checkout, addWorktree(), reset() veya restore() için çalışmaz.
Sunucu tarafı kancalar (pre-receive, update, post-receive, post-update), pre-auto-gc ve post-rewrite hiçbir zaman otomatik olarak çalıştırılmaz.
Kanca ortamı
Pitmaster bir kancayı çalıştırırken şu ortamı iletir:
$env = [
'GIT_DIR' => $this->gitDir,
'GIT_WORK_TREE' => dirname($this->gitDir),
];
Kanca yalnızca şu değişkenleri alır: PATH, HOME ve PHP işleminin diğer tüm değişkenleri aktarılmaz (#13). Kanca betiklerinde mutlak yollar kullanın veya betiğin içinde PATH ayarlayın; #!/usr/bin/env php shebang'i yalnızca sistemin varsayılan yolundaki yorumlayıcıları bulur.
Kanca, normal bir .git dizininin çalışma ağacı olan dirname($gitDir) içinde çalışır.
Kanca betiği biçimi
Kancalar herhangi bir dilde yazılabilir. İlk satır bir shebang olmalıdır:
#!/bin/bash
# Bash hook
#!/usr/bin/env php
<?php
// PHP hook
#!/usr/bin/env python3
# Python hook
Örnek: Pitmaster ile pre-commit
commit() zaten pre-commit, prepare-commit-msg, commit-msg ve post-commit işlemlerini yürüttüğünden uygulama kodunun yalnızca hatayı işlemesi gerekir:
try {
$commitId = $repo->commit('Add feature');
} catch (\RuntimeException $e) {
echo $e->getMessage(); // "pre-commit hook failed"
}
HookRunner öğesini yalnızca ['hooks' => false] ile açılmış bir tanıtıcıda veya Pitmaster tarafından çalıştırılmayan kancalar için kendiniz çağırın.
Örnek kancalar
Git, depoları .sample kanca dosyalarıyla başlatır; Pitmaster::init() boş bir hooks/ dizini oluşturur. Pitmaster öğesinin listHooks() dosyası, .sample dosyalarını hariç tutar:
.git/hooks/
pre-commit.sample (excluded from listHooks)
commit-msg.sample (excluded from listHooks)
pre-commit (included - installed by user)