2

我正在尝试让 git post-receive 挂钩在 Windows 上工作。

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

这就是我所做的:

  1. 更改文件,暂存并提交
  2. 推送到远程服务器 - 成功
  3. 期待看到回声 - 看不到回声
  4. 检查服务器上的工作文件夹 - 最新文件不存在
  5. 登录到服务器并手动运行挂钩脚本 - 最新文件检出到工作文件夹中。

我改变了钩子,所以它除了回显一条消息之外什么都不做,而且我已经读到我应该在推送后在我的控制台中看到这个。但这没有显示,所以我只能假设钩子没有被触发。

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

我假设有人在某处工作,但经过两天的搜索,我发现所有解决方案都无济于事,或者遇到同样问题的人没有得到解答。

(顺便说一句,我是一个 git 新手)。

干杯。

更新

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

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

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

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

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

更新 2

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

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

希望这是最后的障碍,也是它没有执行的原因......

4

2 回答 2

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。

简而言之,更改访问测试,它可能会起作用。

于 2012-02-24T12:38:13.773 回答
0

在服务器上使用 msysgit 并通过文件共享挂钩推送时,现在可以正常工作。自从写了答案以来,这可能已在 mysysgit 中修复。我没有调查它。

我还注意到最初的问题是使用 GitSharp.dll 的 git dot aspx 和 Bonobo。这意味着应用程序不会向 git.exe 发送,并且不会以相同的方式处理挂钩。

例如,在 git dot aspx 中使用的 GitSharp.dll 有它自己的钩子 post-receive 钩子实现,可以在 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 的应用程序之间的混淆。

于 2013-05-26T17:16:59.007 回答