Git - post-receive hook无法在远程Windows服务器上运行

时间:2012-02-23 14:27:16

标签: windows git bonobo

我正在尝试在Windows上使用git post-receive hook。

我正在使用Git 1.7.9(Msysgit)并在本地拥有一个repo,并在远程服务器上拥有一个裸仓库。我可以获取,提交,推送等。我已经设置了一个post-receive挂钩,应该将文件签出到工作文件夹(部署过程的一部分),但它似乎不起作用。

这就是我的所作所为:

  1. 更改文件,暂存并提交
  2. 推送到远程服务器 - 成功
  3. 期待看到回声 - 看不到回声
  4. 检查服务器上的工作文件夹 - 最新文件不存在
  5. 登录服务器并手动运行钩子脚本 - 最新文件将结帐到工作文件夹中。
  6. 我更改了钩子,所以它除了回显消息之外什么都不做,我读过我应该在推送后在控制台中看到这个。但这并没有显示出来,所以我只能假设钩子没有被解雇。

    我正在处理请求的服务器上使用git dot aspx推送HTTP并在本地通过gui进行pusing。在那次失败之后我尝试了Bonobo并且当通过gui或bash控制台推送时钩子不起作用。

    我假设有人在某个地方工作,但经过两天的搜索,我发现所有的解决方案都没有帮助,或者有相同问题的人没有得到答复。

    (我是一个git newbie btw)。

    干杯。

    更新

    我开始认为它可能与权限有关 - 但是Unix权限,而不是NTFS。当@eis提到权限时我假设NTFS。但是经过更多的挖掘后,似乎Windows上的Git仍然会检查Unix文件的权限。

    所以我怀疑问题是后接收文件不可执行,因为当我执行ls -o时它是-rw-r - r--(我相信644)。如果我尝试通过bash和chmod 777 post-receive进行更改,那么执行ls -o权限是相同的。

    奇怪的是,只要我编辑后接收(使用notepad ++),执行位就会被删除。 (我的测试脚本以.bat结尾但确实保留了它的执行位......)

    BTW,我登录的用户是文件的所有者(根据ls -o)但我无法设置权限。

    现在开始变得非常困惑。我错过了一些非常明显的东西吗?

    更新2

    chmod 777 post-receivechmod a+x post-receive都不起作用。我拿了一个新的,干净的post-receive文件,将其上传到服务器并检查权限并执行了。如果我在Windows中重命名文件(删除示例),则删除执行。如果我在使用mv的bash中执行此操作,则保留执行。 但是,每当我编辑文件时(在Windows中或在使用vi的bash中),执行都会被删除。

    所以,现在问题是为什么在编辑文件时它会删除执行位?

    希望这是最后的障碍,并且导致它没有执行......

2 个答案:

答案 0 :(得分:1)

你将不得不修补git来使这项工作。 builtin / receive-pack.c中的检查适用于access(path, X_OK)。在msysgit中,这会转移到mingw_access,它会丢弃X_OK位,因为Windows上不支持它。

在Windows上,我们没有标志来指定文件是可执行的。系统经常对此进行一些仿真。例如,tcl将在PATHEXT环境变量中查找任何扩展,以确定文件是可执行的。我们不能这样做,因为钩子名称是硬编码的,没有任何扩展名。

相反,我建议更改访问测试,只检查文件是否存在,然后在路径上调用execv。 mingw版本(在compat / mingw.c中)查找脚本文件,并将读取shbang行并启动适当的解释器(sh,perl等)。所以修改builtin/receive-pack.c:run_update_hook应该让这对你有用。目前,钩子运行使用start_command,我认为应该为你调用execv。

简而言之,更改访问测试,它可能会有效。

答案 1 :(得分:0)

在服务器上使用msysgit并通过文件共享挂钩现在可以正常工作。也许这是在mysysgit中修复的,因为答案是写的。我没有调查它。

我还注意到原来的问题是git dot aspx和Bonobo正在使用GitSharp.dll。这意味着应用程序没有外壳到git.exe,并且钩子不会以相同的方式处理。

例如,git dot aspx中使用的GitSharp.dll有自己的钩子后接收挂钩实现,可以在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
    }
}

我希望帮助其他人在Git实现的库和调用实际git.exe的应用程序之间产生混淆。