3

I'm trying pre-revprop-change hook script on a Windows machine, but find a tough problem.

I distill my problem to the following scenario:

I have C:\csvn\data\repositories\tr1\hooks\pre-revprop-change.bat with content:

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

testhook.py is:

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)

However, when doing a client-side svn propset svn:log --revprop -r 2 "newtext" , I got python error:

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

What's the cause of this error?

It seems that pre-revprop-change.bat does not pass STDIN handle to the py script. Yes, I verified that pre-revprop-change.bat can fetch text from STDIN(according to instructions in Read stdin stream in a batch file).

I also tried to run pre-revprop-change.bat directly from command line, sys.stdin.read() is OK.

Please kindly help me out.

Screen shot below:

enter image description here

Env:

  • Windows Server 2003
  • Collabnet Subversion Edge 2.3(svn 1.7.3 and Apache 2.2.22)
  • Install Python 2.7.1 msi from python.org

===============[LATEST UPDATE]======================

I'm sorry to say: I should have written in the .bat

exit %ERRORLEVEL%

instead of

exit /b %ERRORLEVEL%

For someone who have tried it with me, please fix it and try again. The /b seems to have pre-revprop-change.bat always exit with 0. TIP: Without /b, running the .bat directly from a cmd window will cause the cmd window to close, so we'd better try it with cmd /c "pre-revprop-change.bat some param".

Quick way to reproduce this problem below

What's more, for those who is still interested, please

then my problem will be reproduced. (Requirement: svn.exe 1.7 command line(whether collabnet or TortoiseSVN), and Python 2.7 installed)

If you still cannot reproduce the error. I've prepared a VMware virtual machine that exhibits the problem exactly. Download the VM at http://down.nlscan.com/misc/chj/winxp-svnhook-py-stdin-error.7z (link expected to be valid until Sep 2013). VMware Player 3.0(free) is sufficient to run that VM.

===============[WORKAROUND FOUND]===================

Very nice workaround provided by @nmenezes, with c:\Python27\python.exe D:\svntest\testhook.py %* in bat .

Community
  • 1
  • 1
Jimm Chen
  • 3,411
  • 3
  • 35
  • 59

2 Answers2

1

SVN is executing the script without an associated console. So you won't see anything displayed on STDOUT. Everything sent to STDERR is displayed as a message on SVN, if the script returns an error code different of 0.

This kind of script should run unattended, it is independent of input or output from the user.

You can try to pass the property value as an extra command line parameter. To do so, change your .bat to:

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

And the .py to:

import os, sys

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

I read the batch STDIN to NEWTEXT variable and I pass it to your script as an extra command line parameter.

This solution does not work for multiple lines values. So, I tried again your original solutions and it worked fine.

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

In this case, the property value is read from the svn.txt file, a text file with multiple lines. In this case, the option with set /p does not work, as we discussed in the comments. But the original script works.

For information, 5 properties are passed on the command line:

1 - repository

2 - revision number

3 - user

4 - property name

5 - operation (M in this case)

The property value is passed on the stdin of the batch script.

@Chen, I finally downloaded the image. The problem is solved when you change the hook batch to:

c:\python27\python.exe d:\svntest\testhook.py %*
exit %ERRORLEVEL%

It looks that the way your XP machine executes python directly is misconfigured.

nmenezes
  • 910
  • 6
  • 12
  • Yes. TESTVAR will contain something from STDIN. But the problem is: once the pre-revprop-change.bat launch some process, that process lose STDIN. – Jimm Chen Sep 18 '12 at 11:58
  • Did you run these lines inside pre-revprop-change.bat ? – nmenezes Sep 18 '12 at 12:56
  • Yes, exactly in pre-revprop-change.bat . – Jimm Chen Sep 18 '12 at 13:16
  • Unfortunately, the ``set /p`` skill does not work well. As stated in this post http://stackoverflow.com/a/6980605/151453 , and confirmed myself, ``set /p`` only reads one line(and probably cannot be called multiple times in order to read all lines). But you know, svn log message may contain may lines. Anyway, thank you for getting involved. – Jimm Chen Sep 18 '12 at 15:44
  • Hi Chen, I tested on my Windows machine... and I got no problems reading stdin with the Python script, as you did on the first post. I'm start to think we are missing something here. I will do another test tomorrow. – nmenezes Sep 18 '12 at 18:48
  • I have an important fix on .bat. Please remove ``/b`` from .bat and try again. – Jimm Chen Sep 19 '12 at 05:31
  • Hi Chen, which version of SVN are you using? I tested your script, that reads from stdin without problems. I also passed a file with multiple lines as the property value and it worked ok. In another test, I tried to read a second time stdin, no problems at all. Are you sure we are testing the same scripts? Do you call any other programs before the python script? – nmenezes Sep 19 '12 at 10:51
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16876/discussion-between-jimm-chen-and-nmenezes) – Jimm Chen Sep 19 '12 at 12:10
  • I've tried quite many versions, on many virtual machines(VM), e.g Collabnet official subversion client 1.7.6, and TortoiseSVN 1.7.7 . I will prepare a WinXP VM(VMware format) that exactly shows the problem on the spot. The VM will be available for download tomorrow. – Jimm Chen Sep 19 '12 at 12:16
  • Chen, the image download broke at 650 MB. I'm downloading it again. I download the quickway you posted, but it works for me. Tested with multiline and it is also works ok. I'm using SVN: svn, version 1.7.6-SlikSvn-1.7.6-X64 (SlikSvn/1.7.6) X64 – nmenezes Sep 21 '12 at 08:13
  • Very nice workaround with ``c:\Python27\python.exe D:\svntest\testhook.py %*``, confirmed. Thank you! But I'm fairly sure I did not do any special config to my Windows and honestly use the python.org Win32 Python 2.7 package. I'll save it for later investigation. – Jimm Chen Sep 24 '12 at 00:54
  • It behaves like pythonw.exe was used for .py files, instead of python.exe. This is the only possible cause I found for the lack of stdin. I checked the registry of the virtual machine and everything looks fine. Good to know it is working now. – nmenezes Sep 24 '12 at 12:47
0

Isn't it up to your batch file to direct the stdin it received into the script that it calls?

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

Maybe you can just prefix the call to your script with the > symbol to have this happen?

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

It seems like if the batch file can read from stdin, then SVN is doing what it is supposed to and it is up to your batch file to make that available to the additional script that you call.

Mark Phippard
  • 10,329
  • 2
  • 32
  • 42
  • I think I got your idea. For workaround, I can tell the .bat to write STDIN content to a tmpfile then later read that tmpfile in my py script. But, the baffle is: Why the py script can inherit STDIN if .bat is run directly from CMD line, but it can't if invoked from svn hook procedure. – Jimm Chen Sep 18 '12 at 13:19
  • Excuse me, I don't know what do you mean by "prefix the call to your script with the > symbol" ... – Jimm Chen Sep 18 '12 at 13:21
  • I fixed the formatting, sorry did not notice it before. Does that answer question about what I meant? – Mark Phippard Sep 18 '12 at 13:23
  • No, writting ``> D:\svntest\testhook.py %*`` in pre-revprop-change.bat wipes out my testhook.py (i.e. testhook.py becomes 0 byte). – Jimm Chen Sep 18 '12 at 14:01
  • Sorry about that, and doh! of course that is what that will do. I wonder if pipe ( | ) would work? You might be able to use the findstr command to read the stdin and then pipe the output into your script. – Mark Phippard Sep 18 '12 at 14:58
  • I have tried the findstr skill in this answer http://stackoverflow.com/a/10824973/151453 in order to have findstr dump STDIN to a file, but in vain; I see findstr falls in dead loop eating 100% CPU. I think findstr also encounters the broken STDIN and goes nuts. – Jimm Chen Sep 18 '12 at 15:31