在subversion pre-revprop-change py脚本中尝试sys.stdin.read()时,为什么会出现“Bad file descriptor”?

时间:2012-09-17 05:03:57

标签: python svn svn-hooks

我正在Windows机器上尝试pre-revprop-change挂钩脚本,但发现一个棘手的问题。

我将我的问题提炼到以下情况:

我有 C:\ csvn \ data \ repositories \ tr1 \ hooks \ pre-revprop-change.bat ,内容为:

D:\svntest\testhook.py %*
exit %ERRORLEVEL%

testhook.py 是:

import os, sys

if __name__ == '__main__':
    # sys.stderr.write(sys.version+'\n') # this is OK, tried.
    newtext = sys.stdin.read() # try to read new log message

    sys.stderr.write('newtext is: %s\n'%newtext)

    exit(2)

但是,在做客户端svn propset svn:log --revprop -r 2 "newtext"时,我遇到了python错误:

Traceback (most recent call last):
  File "D:\svntest\testhook.py", line 5, in <module>
    newtext = sys.stdin.read() # try to read new log message
IOError: [Errno 9] Bad file descriptor

导致此错误的原因是什么?

似乎 pre-revprop-change.bat 没有将STDIN句柄传递给py脚本。是的,我确认 pre-revprop-change.bat 可以从STDIN获取文本(根据Read stdin stream in a batch file中的说明)。

我还尝试直接从命令行运行 pre-revprop-change.bat sys.stdin.read()没问题。

请帮助我。

以下屏幕截图:

enter image description here

ENV:

  • Windows Server 2003
  • Collabnet Subversion Edge 2.3(svn 1.7.3和Apache 2.2.22)
  • 从python.org安装Python 2.7.1 msi

=============== [最新更新] ======================

我很遗憾地说:我应该写在.bat

exit %ERRORLEVEL%

而不是

exit /b %ERRORLEVEL%

对于曾经和我一起试过的人,请修理并再试一次。 /b似乎有pre-revprop-change.bat总是以0退出。提示:如果没有/b,直接从cmd窗口运行.bat会导致cmd窗口关闭,所以我们'最好用cmd /c "pre-revprop-change.bat some param"试一试。

快速重现此问题

对于那些仍然感兴趣的人,请

然后我的问题将被复制。 (要求:svn.exe 1.7命令行(无论是collabnet还是TortoiseSVN),还是安装了Python 2.7)

如果仍然无法重现错误。我准备了一个完全展现问题的VMware虚拟机。在http://down.nlscan.com/misc/chj/winxp-svnhook-py-stdin-error.7z下载VM(链接预计有效期至2013年9月)。 VMware Player 3.0(免费)足以运行该VM。

=============== [发现的办法] ===================

@nmenezes提供了非常好的解决方法,其中c:\Python27\python.exe D:\svntest\testhook.py %*为蝙蝠。

2 个答案:

答案 0 :(得分:1)

SVN正在执行没有关联控制台的脚本。 所以你不会在STDOUT上看到任何东西。 如果脚本返回的错误代码不同于0,则发送到STDERR的所有内容都将在SVN上显示为消息。

这种脚本应该无人值守运行,它独立于用户的输入或输出。

您可以尝试将属性值作为额外的命令行参数传递。 为此,请将.bat更改为:

@echo off
set /p NEWTEXT=
test.py %* %NEWTEXT%
exit /b %ERRORLEVEL%

.py到:

import os, sys

if __name__ == '__main__':   
    newtext = sys.argv[6]
    sys.stderr.write('newtext is: %s\n'% newtext)
    exit(2)

我将批处理STDIN读取到NEWTEXT变量,并将其作为额外的命令行参数传递给您的脚本。

此解决方案不适用于多行值。所以,我再次尝试了你的原始解决方案,它运行良好。

svn propset svn:log --revprop -r 3 -F svn.txt

在这种情况下,从svn.txt文件读取属性值,该文件是一个包含多行的文本文件。在这种情况下,set / p选项不起作用,正如我们在评论中所讨论的那样。但原始剧本有效。

有关信息,在命令行上传递了5个属性:

1 - 存储库

2 - 修订号

3 - 用户

4 - 属性名称

5 - 操作(在这种情况下为M)

属性值在批处理脚本的stdin上传递。

@Chen,我终于下载了图片。将批处理批处理更改为:

时,问题就解决了
c:\python27\python.exe d:\svntest\testhook.py %*
exit %ERRORLEVEL%

看起来XP机器直接执行python的方式配置错误。

答案 1 :(得分:0)

是不是你的批处理文件将它收到的stdin引导到它调用的脚本中?

供参考:http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true

也许您只需使用&gt;为您的脚本添加前缀!是否会发生这种情况?

> D:\svntest\testhook.py %*
exit /b %ERRORLEVEL%

似乎批处理文件可以从stdin中读取,然后SVN正在执行它应该执行的操作,并且由批处理文件决定是否可以使用您调用的其他脚本。