git server-side hooks – maintenance

Hi folks.

Server-side hooks that I wrote previously has one huge shortcoming – Maintenance

How do I modify server-side hooks at the moment?

I edit the hook on a client-side, then commit and push.
After that I connect to a git server via Remote Desktop, and manually update hooks in the corresponding folder.

This is lame. This is a manual process, which causes its own complexity.

Ideally server-side hook should just reuse the hooks being pushed.

But usually git server repo is bare so it will require some special kind of checkout. Which I’ve just blogged šŸ™‚

The following code assumes that hooks are located under Tools/GitHooks folder in git repo


while read oldRef newRef refName
    psCommand=".\\hooks\\HookProxy.ps1 -HookName pre-receive -Arguments \"-OldRef\", \"$oldRef\", \"-NewRef\", \"$newRef\", \"-RefName\", \"$refName\""
    c:/windows/system32/WindowsPowerShell/v1.0/PowerShell.exe -Sta -ExecutionPolicy RemoteSigned -NoProfile -Command "$psCommand"


    if [ $exitCode != 0 ]
        exit $exitCode


#requires -version 2.0

    [string] $HookName,
    [object[]] $Arguments

$script:ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }

Trap { throw $_ }

function Main
    $tempDir = [Guid]::NewGuid()
    New-Item -Path $tempDir -ItemType Directory | Out-Null

        Git-CheckoutFile -Branch master -RelativeFilePath Tools\GitHooks -DestinationFolder $tempDir

        Invoke-Expression "$tempDir\GitHooks\$HookName.ps1 $Arguments"
        Remove-Item -Path $tempDir -Recurse -Force


function Git-CheckoutFile
        [string] $Branch,
        [string] $RelativeFilePath,
        [string] $DestinationFolder

    if ($RelativeFilePath -eq ".")
        $RelativeFilePath = "*"

    $RelativeFilePath = $RelativeFilePath -replace "\\", "/"

    $tempDir = [Guid]::NewGuid()
    New-Item -Path $tempDir -ItemType Directory | Out-Null

    git archive $Branch $RelativeFilePath --output "$tempDir\__temp.tar"
    tar -xf "$tempDir/__temp.tar" -C $tempDir
    Remove-Item "$tempDir/__temp.tar"

    if (-not (Test-Path $DestinationFolder))
        New-Item -Path $DestinationFolder -ItemType Directory | Out-Null

    Copy-Item -Path "$tempDir/$RelativeFilePath" -Destination $DestinationFolder -Recurse

    Remove-Item -Path $tempDir -Recurse -Force


Absolutely the same approach could be used for other server-side hooks such as post-receive

And this works as expected

The idea is very simple. We write a proxy (HookProxy.ps1) which will extract corresponding hook from a repo and execute it.
So HookProxy.ps1 is the only piece of code should be deployed once to the server, and later on all hooks modifications are made via source control (master branch).

P.S. I’ve just realized that this can be useful for client-side hooks as well. It will get rid of the need to keep hooks updated in all possible branches.


About mnaoumov

Senior .NET Developer in Readify
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

2 Responses to git server-side hooks – maintenance

  1. Pingback: git checkout on bare repo | mnaoumov.NET

  2. Pingback: git hook proxy | mnaoumov.NET

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s