Subversion 客户端挂钩不显示回显
Subversion client hook doesn't show echo
这是我的预提交挂钩。当我开始提交时,我的外部差异工具会弹出,但 cmd window 什么都不显示,它也不会读取我的键盘输入。
@echo off
for /F "usebackq" %%i IN (%1) DO (svn diff %%i >nul)
echo hello
choice /M "Continue to commit?"
SET userChoice=%ERRORLEVEL%
IF %userChoice% equ 1 exit /b 0
IF %userChoice% equ 2 exit /b 1
我错过了什么吗?
根据 help documentation of TortoiseSVN,您需要显式重定向到控制台(设备 con
):
When debugging hook scripts you may want to echo progress lines to the DOS console, or insert a pause to stop the console window disappearing when the script completes. Because I/O is redirected this will not normally work. However you can redirect input and output explicitly to CON to overcome this. e.g.
echo Checking Status > con
pause < con > con
不幸的是,这不适用于 choice
命令,因为它似乎不接受从设备 con
:
重定向的输入
>>> choice < con
ERROR: The handle is invalid.
一个简单的解决方法是使用支持从 con
:
重定向的 set /P
命令
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Loop structure for prompting user:
:CONFIRM
rem // Display prompt and await user input:
< con > con set /P SELECT="Continue? [Yes/No]?"
rem // Check user input case-insensitively:
if /I "%SELECT%"=="Y" exit /B 0
if /I "%SELECT%"=="Yes" exit /B 0
if /I "%SELECT%"=="N" exit /B 1
if /I "%SELECT%"=="No" exit /B 1
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
endlocal
exit /B
这样做的缺点是条目需要用RETURN来终止,与choice
命令相反,后者接受单-按键输入。
这里有一个更好的方法,它具有类似于 choice
命令的单键提示。这(误)使用 xcopy
命令及其接受重定向输入到提供 /W
开关时出现的复制确认提示的能力。也看看注释:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Loop structure for prompting user:
:CONFIRM
rem // Display prompt without trailing line-break:
< nul > con set /P ="Continue? [Y/N]?"
rem /* Let `xcopy` wait for a single-key entry using its `/W` switch;
rem `/L` tells `xcopy` to actually copy nothing; to avoid problems
rem with inexistent paths, use this script's path as source file
rem and the system's temporary directory as the target location: */
< con (
for /F "delims=" %%L in ('
xcopy /L /W "%~f0" "%TMP%\"
') do (
rem /* Capture the copy confirmation prompt of `xcopy /L /W`,
rem `Press any key when ready to begin copying file(s)`,
rem together with the character entered by the user, which
rem is appended to the prompt message: */
set "CHAR=%%L"
rem /* Leave loop upon first iteration, because we are not
rem interested in any copying results and summaries: */
goto :SKIP
)
)
:SKIP
rem // Extract the last character, which is the actual user input:
set "CHAR=!CHAR:~-1!"
rem // Display user entry:
> con echo(!CHAR!
rem // Check user input case-insensitively:
if /I "!CHAR!"=="Y" exit /B 0
if /I "!CHAR!"=="N" exit /B 1
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
endlocal
exit /B
如果提供了意外输入,将在下一行重新打印提示并等待新的用户输入。
为避免在意外用户输入的情况下重新打印提示文本,请使用以下脚本:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "MESSAGE=Confirm? [Y/N]?"
rem // Retrieve back-space character:
for /F %%Z in ('prompt $H ^& for %%Z in ^(.^) do rem/') do set "BS=%%Z"
rem // Retrieve carriage-return character:
for /F %%Z in ('copy /Z "%~f0" nul') do set "CR=%%Z"
rem // Loop structure for prompting user:
:CONFIRM
setlocal EnableDelayedExpansion
rem // Display prompt without trailing line-break:
> con < nul set /P ="%BS% !CR!!MESSAGE!"
endlocal
rem /* Let `xcopy` wait for a single-key entry using its `/W` switch;
rem `/L` tells `xcopy` to actually copy nothing; to avoid problems
rem with inexistent paths, use this script's path as source file
rem and the system's temporary directory as the target location: */
< con (
for /F "delims=" %%L in ('
xcopy /L /W "%~f0" "%TMP%\"
') do (
rem /* Capture the copy confirmation prompt of `xcopy /L /W`,
rem `Press any key when ready to begin copying file(s)`,
rem together with the character entered by the user, which
rem is appended to the prompt message: */
set "CHAR=%%L"
rem /* Leave loop upon first iteration, because we are not
rem interested in any copying results and summaries: */
goto :SKIP
)
)
:SKIP
setlocal EnableDelayedExpansion
rem // Extract the last character, which is the actual user input:
set "CHAR=!CHAR:~-1!"
rem // Display user entry without trailing line-break:
> con < nul set /P ="!CHAR!"
rem // Check user input case-insensitively:
if /I "!CHAR!"=="Y" exit /B 0
if /I "!CHAR!"=="N" exit /B 1
endlocal
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
echo/
endlocal
exit /B
这是一个全面的解决方案,允许使用 !
、^
和 "
等特殊字符。
这是一个非常相似的解决方案,它依赖于 replace
命令及其 /W
开关,在出现意外的用户输入时也不会重新打印提示。由于 replace
将按键字符打印在单独的一行中,因此无需将其与另一个字符串分开(与 xcopy /W
相反):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "MESSAGE=Confirm? [Y/N]?"
rem // Retrieve back-space character:
for /F %%Z in ('prompt $H ^& for %%Z in ^(.^) do rem/') do set "BS=%%Z"
rem // Retrieve carriage-return character:
for /F %%Z in ('copy /Z "%~f0" nul') do set "CR=%%Z"
rem // Loop structure for prompting user:
:CONFIRM
setlocal EnableDelayedExpansion
rem // Display prompt without trailing line-break:
> con < nul set /P ="%BS% !CR!!MESSAGE!"
endlocal
rem /* Let `replace` wait for a single-key entry using its `/W` switch;
rem `/U` tells `replace` to actually do nothing; to avoid problems
rem with inexistent paths, use this script's path as source file
rem and its parent directory as the target location: */
< con (
for /F "skip=1 delims=" %%L in ('
replace /W /U "%~f0" "."
') do (
rem /* Capture the confirmation user input of `replace /W /U`,
rem skipping the prompt `Press any key to continue . . .`: */
set "CHAR=%%L"
rem /* Leave loop upon first iteration, because we are not
rem interested in any replacement results and summaries: */
goto :SKIP
)
)
:SKIP
setlocal EnableDelayedExpansion
rem // Display user entry without trailing line-break:
> con < nul set /P ="!CHAR!"
rem // Check user input case-insensitively:
if /I "!CHAR!"=="Y" exit /B 0
if /I "!CHAR!"=="N" exit /B 1
endlocal
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
echo/
endlocal
exit /B
这是我的预提交挂钩。当我开始提交时,我的外部差异工具会弹出,但 cmd window 什么都不显示,它也不会读取我的键盘输入。
@echo off
for /F "usebackq" %%i IN (%1) DO (svn diff %%i >nul)
echo hello
choice /M "Continue to commit?"
SET userChoice=%ERRORLEVEL%
IF %userChoice% equ 1 exit /b 0
IF %userChoice% equ 2 exit /b 1
我错过了什么吗?
根据 help documentation of TortoiseSVN,您需要显式重定向到控制台(设备 con
):
When debugging hook scripts you may want to echo progress lines to the DOS console, or insert a pause to stop the console window disappearing when the script completes. Because I/O is redirected this will not normally work. However you can redirect input and output explicitly to CON to overcome this. e.g.
echo Checking Status > con pause < con > con
不幸的是,这不适用于 choice
命令,因为它似乎不接受从设备 con
:
>>> choice < con ERROR: The handle is invalid.
一个简单的解决方法是使用支持从 con
:
set /P
命令
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Loop structure for prompting user:
:CONFIRM
rem // Display prompt and await user input:
< con > con set /P SELECT="Continue? [Yes/No]?"
rem // Check user input case-insensitively:
if /I "%SELECT%"=="Y" exit /B 0
if /I "%SELECT%"=="Yes" exit /B 0
if /I "%SELECT%"=="N" exit /B 1
if /I "%SELECT%"=="No" exit /B 1
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
endlocal
exit /B
这样做的缺点是条目需要用RETURN来终止,与choice
命令相反,后者接受单-按键输入。
这里有一个更好的方法,它具有类似于 choice
命令的单键提示。这(误)使用 xcopy
命令及其接受重定向输入到提供 /W
开关时出现的复制确认提示的能力。也看看注释:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Loop structure for prompting user:
:CONFIRM
rem // Display prompt without trailing line-break:
< nul > con set /P ="Continue? [Y/N]?"
rem /* Let `xcopy` wait for a single-key entry using its `/W` switch;
rem `/L` tells `xcopy` to actually copy nothing; to avoid problems
rem with inexistent paths, use this script's path as source file
rem and the system's temporary directory as the target location: */
< con (
for /F "delims=" %%L in ('
xcopy /L /W "%~f0" "%TMP%\"
') do (
rem /* Capture the copy confirmation prompt of `xcopy /L /W`,
rem `Press any key when ready to begin copying file(s)`,
rem together with the character entered by the user, which
rem is appended to the prompt message: */
set "CHAR=%%L"
rem /* Leave loop upon first iteration, because we are not
rem interested in any copying results and summaries: */
goto :SKIP
)
)
:SKIP
rem // Extract the last character, which is the actual user input:
set "CHAR=!CHAR:~-1!"
rem // Display user entry:
> con echo(!CHAR!
rem // Check user input case-insensitively:
if /I "!CHAR!"=="Y" exit /B 0
if /I "!CHAR!"=="N" exit /B 1
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
endlocal
exit /B
如果提供了意外输入,将在下一行重新打印提示并等待新的用户输入。
为避免在意外用户输入的情况下重新打印提示文本,请使用以下脚本:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "MESSAGE=Confirm? [Y/N]?"
rem // Retrieve back-space character:
for /F %%Z in ('prompt $H ^& for %%Z in ^(.^) do rem/') do set "BS=%%Z"
rem // Retrieve carriage-return character:
for /F %%Z in ('copy /Z "%~f0" nul') do set "CR=%%Z"
rem // Loop structure for prompting user:
:CONFIRM
setlocal EnableDelayedExpansion
rem // Display prompt without trailing line-break:
> con < nul set /P ="%BS% !CR!!MESSAGE!"
endlocal
rem /* Let `xcopy` wait for a single-key entry using its `/W` switch;
rem `/L` tells `xcopy` to actually copy nothing; to avoid problems
rem with inexistent paths, use this script's path as source file
rem and the system's temporary directory as the target location: */
< con (
for /F "delims=" %%L in ('
xcopy /L /W "%~f0" "%TMP%\"
') do (
rem /* Capture the copy confirmation prompt of `xcopy /L /W`,
rem `Press any key when ready to begin copying file(s)`,
rem together with the character entered by the user, which
rem is appended to the prompt message: */
set "CHAR=%%L"
rem /* Leave loop upon first iteration, because we are not
rem interested in any copying results and summaries: */
goto :SKIP
)
)
:SKIP
setlocal EnableDelayedExpansion
rem // Extract the last character, which is the actual user input:
set "CHAR=!CHAR:~-1!"
rem // Display user entry without trailing line-break:
> con < nul set /P ="!CHAR!"
rem // Check user input case-insensitively:
if /I "!CHAR!"=="Y" exit /B 0
if /I "!CHAR!"=="N" exit /B 1
endlocal
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
echo/
endlocal
exit /B
这是一个全面的解决方案,允许使用 !
、^
和 "
等特殊字符。
这是一个非常相似的解决方案,它依赖于 replace
命令及其 /W
开关,在出现意外的用户输入时也不会重新打印提示。由于 replace
将按键字符打印在单独的一行中,因此无需将其与另一个字符串分开(与 xcopy /W
相反):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "MESSAGE=Confirm? [Y/N]?"
rem // Retrieve back-space character:
for /F %%Z in ('prompt $H ^& for %%Z in ^(.^) do rem/') do set "BS=%%Z"
rem // Retrieve carriage-return character:
for /F %%Z in ('copy /Z "%~f0" nul') do set "CR=%%Z"
rem // Loop structure for prompting user:
:CONFIRM
setlocal EnableDelayedExpansion
rem // Display prompt without trailing line-break:
> con < nul set /P ="%BS% !CR!!MESSAGE!"
endlocal
rem /* Let `replace` wait for a single-key entry using its `/W` switch;
rem `/U` tells `replace` to actually do nothing; to avoid problems
rem with inexistent paths, use this script's path as source file
rem and its parent directory as the target location: */
< con (
for /F "skip=1 delims=" %%L in ('
replace /W /U "%~f0" "."
') do (
rem /* Capture the confirmation user input of `replace /W /U`,
rem skipping the prompt `Press any key to continue . . .`: */
set "CHAR=%%L"
rem /* Leave loop upon first iteration, because we are not
rem interested in any replacement results and summaries: */
goto :SKIP
)
)
:SKIP
setlocal EnableDelayedExpansion
rem // Display user entry without trailing line-break:
> con < nul set /P ="!CHAR!"
rem // Check user input case-insensitively:
if /I "!CHAR!"=="Y" exit /B 0
if /I "!CHAR!"=="N" exit /B 1
endlocal
rem // Repeat prompt in case of invalid entry:
goto :CONFIRM
echo/
endlocal
exit /B