Pāriet uz saturu

Āķi

Git āķi ir izpildāmi skripti .git/hooks/, kas darbojas noteiktos git darbību brīžos. Pitmaster nosaka un izsauc āķus, izmantojot PHP procesu vadību (proc_open).

Āķi tiek palaisti pēc noklusējuma

Repozitorija darbības automātiski palaiž āķus, kas uzskaitīti sadaļā Āķi Pitmaster izpilda. Lai tos izslēgtu repozitorija tvērumam, norādiet opcijas, to atverot:

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() un Pitmaster::clone() pieņem vienas un tās pašas opcijas. Āķa palaišanai nepieciešams proc_open(); vidēs, kur tas ir atspējots, atveriet repozitorijus ar ['hooks' => false]. CLI vienmēr atver repozitoriju ar ieslēgtiem āķiem.

Pitmaster meklē āķus tikai mapē <gitDir>/hooks. Tas ignorē core.hooksPath, bet saistītā darbkokā meklē mapē .git/worktrees/<name>/hooks, tāpēc koplietotie skripti .git/hooks tur nedarbojas (#12).

HookRunner, kas aprakstīts tālāk, ignorē šīs opcijas: izsaucot to tieši, āķis vienmēr tiek palaists.

HookRunner

PHP
use Pitmaster\Hooks\HookRunner;

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

Pārbaude, vai āķis pastāv

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

Āķis pastāv, ja fails atrodas šeit: .git/hooks/<name>, un ir izpildāms.

Āķa palaišana

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

Ar argumentiem

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

Ar stdin

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

Āķis pre-push saņem ref informāciju, izmantojot stdin.

Veiksmīgas izpildes pārbaude

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

runAndCheck() ir palīgfunkcija, kas palaiž āķi un atgriež true, ja izejas kods ir 0. Ja āķa nav, tā atgriež true (ja āķa nav, tas nav iebildums).

Instalēto āķu saraksts

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

Uzskaita visus izpildāmos failus mapē .git/hooks/ (izņemot .sample failus).

run() neesošam vai neizpildāmam āķim atgriež 0 izejas kodu un tukšu izvadi. Ja procesu nevar palaist, tas atgriež 1 izejas kodu un izvada Failed to start hook uz stderr.

Āķa instalēšana

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

Ieraksta skripta saturu failā .git/hooks/<name> un iestata izpildes atļauju (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);

Āķi, ko izpilda Pitmaster

HookRunner var izpildīt jebkuru āķi pēc nosaukuma. Repository automātiski izpilda šos āķus:

Āķis Izpilda Argumenti Var pārtraukt?
pre-commit commit() nav Jā (izejas kods nav nulle)
prepare-commit-msg commit() ziņojuma fails, pēc tam message (vai merge, pabeidzot sapludināšanu) Jā
commit-msg commit() ziņojuma fails (.git/COMMIT_EDITMSG); faila izmaiņas tiek izmantotas Jā (izejas kods nav nulle)
post-commit commit() nav Nē (informatīvs)
pre-rebase rebase() augšupējā versija Jā
post-checkout checkout() vecais HEAD, jaunais HEAD, 1 Nē (informatīvs)
post-merge merge(), mergeOctopus(), mergeContinue() 0 Nē (informatīvs)
pre-push push() un tā varianti attālā repozitorija nosaukums, URL; ref rindas stdin ievadē Jā (izejas kods nav nulle)

Ja āķa izpilde neizdodas, darbība izraisa RuntimeException('<name> hook failed'); āķa izvade netiek iekļauta. Commit āķi tiek palaisti tikai no commit(): merge() izveidoti sapludināšanas komiti tos nepalaiž. post-checkout netiek palaists, ja izmanto addWorktree(), reset() vai restore().

Servera puses āķi (pre-receive, update, post-receive, post-update), pre-auto-gc un post-rewrite nekad netiek palaisti automātiski.

Āķa vide

Kad Pitmaster palaiž āķi, tas nodod šādu vidi:

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

Šie ir vienīgie mainīgie, ko saņem āķis: PATH, HOME un visi pārējie PHP procesa mainīgie netiek nodoti tālāk (#13). Āķa skriptos izmantojiet absolūtos ceļus vai iestatiet PATH pašā skriptā; #!/usr/bin/env php shebang atrod interpretatorus tikai sistēmas noklusējuma ceļā.

Āķis darbojas mapē dirname($gitDir), kas parastam .git direktorijam ir darbkoks.

Āķa skripta formāts

Āķus var rakstīt jebkurā valodā. Pirmajai rindai jābūt shebang rindai:

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

Piemērs: pre-commit ar Pitmaster

commit() jau izpilda pre-commit, prepare-commit-msg, commit-msg un post-commit, tāpēc lietotnes kodam jāapstrādā tikai kļūmes gadījums:

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

Izsauciet HookRunner paši tikai ar apstrādātāju, kas atvērts ar ['hooks' => false], vai āķiem, ko Pitmaster nepalaiž.

Āķu piemēri

Git inicializē repozitorijus ar .sample āķu failiem; Pitmaster::init() izveido tukšu hooks/ direktoriju. Pitmaster listHooks() ignorē .sample failus:

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