İçeriğe geç

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:

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() 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

PHP
use Pitmaster\Hooks\HookRunner;

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

Kancanın mevcut olup olmadığını denetleme

PHP
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

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

Bağımsız değişkenlerle

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

Standart girdiyi kullanarak

PHP
$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

PHP
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

PHP
$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

PHP
$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).

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);

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:

PHP
$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:

Kabuk
#!/bin/bash
# Bash hook
PHP
#!/usr/bin/env php
<?php
// PHP hook
Python
#!/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:

PHP
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:

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