2

I'm trying to get a git post-receive hook working on Windows.

I'm using Git 1.7.9 (Msysgit) and have a repo locally and a bare repo on a remote server. I can fetch, commit, push etc. I've set up a post-receive hook that should checkout the files into a working folder (part of the deployment process) but it doesn't seem to work.

Here's what I do:

  1. Change a file, stage and commit it
  2. Push to remote server - successfully
  3. Expect to see the echo - don't see the echo
  4. Check working folder on server - latest files are not there
  5. Log onto the server and run the hook script manually - latest files are checkout out into the working folder.

I changed the hook so it does nothing except echo a message and I've read that I should see this in my console after pushing. But this is not being displayed so I can only assume the hook is not being fired off.

I'm pushing over HTTP with git dot aspx on the server handling the request and pusing via the gui locally. After that failed I tried Bonobo and the hook doesn't work when pushing via the gui or a bash console.

I'm assuming someone has this working somewhere but after two days of searching all I have found are solutions that don't help or people with the same problem that has gone unanswered.

(I'm a git newbie btw).

Cheers.

Update

I'm starting to think it may be to do with permissions - but Unix permissions, rather than NTFS. When @eis mentioned permissions I had assumed NTFS. But after more digging it seems that Git on Windows still checks for Unix file perms.

So I suspect the issue is that the post-receive file is not executable as when I do a ls -o it's -rw-r--r-- (644 I believe). If I try and change this through bash and chmod 777 post-receive then do ls -o the permissions are the same.

The strange this is that as soon as I edited post-receive (with notepad++) the execute bit gets removed. (my test script that ends in .bat does retain its execute bits though...)

BTW, the user I'm logged on as is the owner of the files (according to ls -o) and yet I can't set the permissions.

Starting to get really confused now. Am I missing something really obvious?

Update 2

Neither chmod 777 post-receive nor chmod a+x post-receive work. I took a new, clean post-receive file, uploaded it the to the server and checked the permissions and it had execute. If I rename the file (to remove sample) in Windows then execute is removed. If I do it in bash with mv execute is retained. But, whenever I edit the file (in Windows or in bash with vi) then execute gets removed.

So, the problem now is why does it remove the execute bits when I edit the file?

Hopefully this is the final hurdle and the cause of it not executing...

Jag
  • 723
  • 8
  • 21
  • Are you sure your script is correct and it executes? Do you have any logging there? What about git-dot-aspx, does it have any logs? – vissi Feb 23 '12 at 15:38
  • When I log onto the server and run it manually via a bash console it does as expected (ie echo and checkout some files). This tells me the script is fine. However when I push to this repo it does not fire off - I don't see the echo and the files are not checked out. This tells me the script is not being called. As for logs. Nothing in event viewer, can't find any gitdotaspx logs and Bonobo has logs but no errors. – Jag Feb 23 '12 at 16:00
  • It should work, and it shouldn't matter whichever client you use. Few things you could check: - shebang line in the script - does it point to something meaningful? Does the script work using shell mentioned there? - are execution permissions set correctly for the script, does the user runnig git repo have correct permissions? - you do have your line endings correct on that script, right? (though you would see an error about this) – eis Feb 23 '12 at 16:52
  • first line is `#!/bin/sh`. I assumed that the gitsharp lib that gotdotaspx and Bonobo are built on would run that in the relevant context. Now that you mentioned it I'm starting to think that it should point to `C:\Program Files (x86)\Git\bin\sh.exe`, which if I execute, I get `sh-3.1$` prompt. – Jag Feb 23 '12 at 17:15
  • Sorry, still getting used to SO :) I don't know how to navigate to or execute the script in bash so I can't test this bit. NTFS perms I think are fine. The site runs as network service which as full control over the repo/deploy folders. (test environment). I am an admin over the repos (set using Bonobo). I'm using Notepad++ and started with post-receive.sample file so I'm assuming Notepad++ hasn't altered any line – Jag Feb 23 '12 at 17:31
  • After more digging I changed the post-receive hook to: `"C:\Program Files (x86)\Git\bin\sh.exe" --login -i -c "GIT_WORK_TREE=/d/Sites/GitTestSite git checkout -f" echo "done"` Again, running from bash it executes and copies the latest files to the working directory. If I add .bat to the hook filename I can run it from a windows command prompt and it works from there too. Definitely looks like the hook is not being run after a push for some reason. – Jag Feb 24 '12 at 10:29

2 Answers2

1

You are going to have to patch git to make this work. The checks in builtin/receive-pack.c are for access(path, X_OK). In msysgit this diverts to mingw_access which throws away the X_OK bit as it is simple not supported on Windows.

On windows, we have no flag to specify a file is executable. Systems often do some emulation of this. For instance, tcl will look for any extension in the PATHEXT environment variable to decide that a file is executable. We can't do that here as the hook names are hardcoded without any extensions.

Instead, I suggest changing the access test to just check the file exists and then call execv on the path. The mingw version of this (in compat/mingw.c) looks for script files and will read the shbang line and launch an appropriate interpreter (sh, perl etc). So modifying builtin/receive-pack.c:run_update_hook should let this work for you. Currently the hook running uses start_command and I think that should call down to execv for you.

In short, change the access test and it will probably work.

patthoyts
  • 32,320
  • 3
  • 62
  • 93
  • Thanks for the info @patthoyts, I'm downloading the source now and will have a look. Not feeling overly confident though - I only just managed to understand what you were saying. (no offence to your knowledge, just mine :) Am I being naive in thinking this should work off the shelf? After all if hooks are an integral part of Git surely a git solution for windows should support this? – Jag Feb 24 '12 at 12:57
  • Only if someone actually made it work. I don't know any other people, but while I use msysGit on Windows I host all my central repositories on linux. Any Windows to windows pulling is between developer workstations and has never required any hooks. If you test this out and it works, then you can submit the patch and solve this for everyone. – patthoyts Feb 24 '12 at 14:54
  • Yeah, I figured there's still a lot of reliance on nix in Git. I downloaded the source and had a look at where you suggested. Most of it makes sense but I'm not confident enough (and don't really have the time) to resolve it myself. I thought I'd take the time to have a play with Git in between project work but it seems a little too much effort at the moment. I will credit you with the answer though as it is correct. Thanks for your time. – Jag Feb 24 '12 at 15:14
0

When using msysgit on the server and pushing via a file share hooks work without problem now. Maybe this was fixed in mysysgit since the answer was written. I didn't look into it.

I also noticed that the original question stated git dot aspx and Bonobo were being used which use GitSharp.dll. This would mean the application is not shelling out to the git.exe and hooks would not be handled the same way.

For example, the GitSharp.dll used in git dot aspx has it's own hook post-receive hook implementation which could be performed in C#:

public void Receive(Stream inputStream, Stream outputStream) 
{
    using (var repository = GetRepository()) 
    {
        var pack = new ReceivePack(repository);
        pack.setBiDirectionalPipe(false);

        //setup post receive hook here
        pack.setPostReceiveHook(new PostRecieveHook());

        pack.receive(inputStream, outputStream, outputStream);
     }
}


public class PostRecieveHook : IPostReceiveHook 
{
    public void OnPostReceive(ReceivePack rp, ICollection<ReceiveCommand> commands) 
    {
        //Do PostRecieve Hook Work Here
    }
}

I hope to help others with confusion between libraries that are implementations of Git and applications that call out to the actual git.exe.

Jason Rowe
  • 6,216
  • 1
  • 33
  • 36
  • Thanks for the update. I'll check it out. (Still haven't got this solved yet :)) – Jag Oct 01 '13 at 11:12