We are using SVN and I would like to check the commit message for an string and give a warning that commits without this string will be bounced starting next month but currently allow the commit through.
stderr is only outputted when the commit fails, how do I allow the commit to succeed but still provide output to the user (I am writing the hook in C#)?
Per your response above, here is the windows batch solution.
In the post-commit hook
:: repos = full path to physical repository
:: rev = the revision number related to the transaction committed
:: reposname = the name of the repository
set repos=%1
set rev=%2
set reposname=%~nx1
set Unwanted_String=string value
:: Capture commit message
svnlook log %repos% -r %rev%>%reposname%_%rev%_commit_statement.txt
:: Verify commit message meets requirements
powershell -command "If (Get-Content '%reposname%_%rev%_commit_statement.txt' | Where-Object { $_ -match '%Unwanted_String%'}) {'Found'} else {'Not found'}">%reposname%_%rev%_Is_String_Present.txt
:: Determine if feedback is needed
set /p Commit_Search=<%reposname%_%rev%_Is_String_Present.txt
if "%Commit_Search%"=="Found" (
echo ----------------------------------------------------->&2
echo The string %Unwanted_String% is not allowed >&2
echo In the future, please do not include this as part of your commit statement >&2
echo. >&2
echo Your change has been committed>&2
echo ----------------------------------------------------->&2
del *%reposname%_%rev%*.txt
exit /b 1
)
The output back to the user will show the object was committed along with an error message
post-commit hook failed (exit code 1) with output:
The string xxxxxx is not allowed
In the future, please do not include this as part of your commit statement
Your change has been committed
Once the grace period is over and you want to reject commit statements that contain this string, move the above lines to your pre-commit hook with one change
:: Capture commit message (-t is transaction in progress)
svnlook log -t %rev% %repos%>%reposname%_%rev%_commit_Statement.txt
Moving this to the pre-commit hook will prevent the commit and inform the user as to why it was rejected.
Related
I have a dotnet core container app (linux) using the following code to make an async SELECT call to db2 (z/os):
var result = new DataTable();
var query = "SELECT * FROM DB.TABLE WITH UR;"
using (var connection = new DB2Connection(_connection))
{
await connection.OpenAsync();
using (var command = new DB2Command(query, connection))
{
using (var myReader = await command.ExecuteReaderAsync()) // fails here when query > 1190 chars
{
result.Columns.AddRange(myReader.GetColumnSchema()
.Select(x => new DataColumn(x.ColumnName, x.DataType))
.ToArray());
result.BeginLoadData();
while (await myReader.ReadAsync())
{
var contents = new object[myReader.FieldCount];
myReader.GetValues(contents);
result.LoadDataRow(contents, false);
}
result.EndLoadData();
}
}
}
This code works fine for any query under 1190 characters. When I increase the sql string to 1191 characters or more, the call hangs and times out with the following error:
IBM.Data.DB2.Core.DB2Exception (0x80004005): ERROR [08001] [IBM] SQL30081N A communication error has been detected. Communication protocol being used: "TCP/IP". Communication API being used: "SOCKETS". Location where the error was detected: "170.2.8.84". Communication function detecting the error: "recv". Protocol specific error code(s): "110", "", "". SQLSTATE=08001
The issue does not occur when running with Docker locally. I am unable to run Windows containers on the culprit host, so that comparison is unavailable.
Client:
# db2level
DB21085I This instance or install (instance name, where applicable: "*") uses
"64" bits and DB2 code release "SQL11055" with level identifier "0606010F".
Informational tokens are "DB2 v11.5.5.1", "s2103171200", "DYN2103171200AMD64",
and Fix Pack "1".
Product is installed at "/app/clidriver".
A DBA was unable to see any activity for the timed out queries. What could be impeding these calls based on this specific size threshold?
To test if your db2cli can execute the same SQL statement (i.e. independently of C# and independently of .net core, you can copy and modify the script below, by copying the hostname, username, password, and port number from your credentials json file (or wherever you received your connection string details).
If your connection is NOT encrypted with SSL/TLS, modify the script to remove the Security=SSL parameters from the database and dsn definitions below, and use the correct non-SSL port-number.
If your password contains any characters that are considered special by your linux shell, escape each such special character by a backslash \ when assigning the password variable below in the script. Otherwise you will get SQL30082N reason "24".
After you modify this file, chmod +x the file, and run it.
#!/bin/bash
#
# populate db2dsdriver.cfg for Db2-on-cloud lite and verify db2cli connects and runs SQL statements.
#
# Prereq: (1) an IBM Db2 CLI driver is already installed and on the PATH for current userid.
# Prereq: (2) the version of the CLI driver matches the version of the Db2-lite instance (per the UI dashboard)
# Prereq: (3) after you modify this file, remember to `chmod +x` this file before running it.
#
# This script works with clidriver , with the Db2 runtime client, with the Db2 data server client (fat client).
# Can re-run this script, overwrites current matching entries in db2dsdriver.cfg (if exists) else creates that file.
#
# For IBM Db2-on-cloud (lite plan , kostenlos ).
# Configure the db2dsdriver.cfg file for use with db2cli tool to connect to Db2-on-cloud from command-line bash.
#
# You must modify the variable-values below by copying username, password, port, hostname from your credentials json file.
# And remember to escape ( precede with \) any and all special-character in password, otherwise connect will fail.
#
# Note 1: this expects the Db2-on-cloud hostname to have SSL/TLS encrypted-connections to BLUDB which is the default
# for all IBM Db2-on-cloud hostnames ending with pattern *appdomain.cloud
#
# Note 2: at clidriver version 11.5.6.0 , db2cli tool can return exit-code 0 even on failure, doh!
#
# Note 3: to get your username and password, host and port-number , download the credentials json file and view it to see them.
# Then copy their values into the appropriate variables below before making this script executable and run it.
#
set -u
typeset which=/usr/bin/which
typeset db2cli=$( ${which} db2cli )
[[ -z ${db2cli:=""} ]] && print "\nERROR: please either dot in a db2profile to allow db2cli to be on the PATH\nor edit your PATH environment variable to put the clidriver/bin directory on the PATH" && exit 1
typeset dbname=bludb # default database-name for Db2-on-cloud lite plan shared databases.
typeset hostname="change me"
typeset ssl_port_number=32733 # from credentials json
typeset password="change me" # remember to escape \ any special characters here, copy from credentials json file.
typeset username="change me" # copy from credentials json file.
typeset dbalias=bludb # you can use whatever alias-name you like, 8 bytes long max
typeset input_sql_tmpfile=/tmp/db2cli_inputsql.sql
${db2cli} writecfg add -database ${dbname} -host ${hostname} -port ${ssl_port_number} -parameter Security=SSL
rc=$?
(( rc > 0 )) && print "\nERROR: failed to write the database to the config file\n" && exit 1
${db2cli} writecfg add -dsn ${dbalias} -database ${dbname} -host ${hostname} -port ${ssl_port_number} -parameter Security=SSL
rc=$?
(( rc > 0 )) && print "\nERROR: failed to write the dsn to the config file\n" && exit 1
${db2cli} validate -dsn ${dbalias} -connect -user ${username} -passwd ${password}
rc=$?
(( rc > 0 )) && print "\nERROR: failed to connect to the dsn with supplied credentials\n" && exit 1
# Verify that the db2cli tool can run some SQL statements by putting them into a file and passing the file to db2cli
#create an inputfile containing SQL statements ( make a temp file for this purpose)
# note that the default statement delimiter for db2cli is crlf (or lf on linux) not semicolon as with db2clp.
echo "values current timestamp" > ${input_sql_tmpfile}
echo "values current server" >> ${input_sql_tmpfile}
echo "values current user" >> ${input_sql_tmpfile}
${db2cli} execsql -execute -dsn ${dbalias} -user ${username} -passwd ${password} -inputsql ${input_sql_tmpfile}
I have a C# solution in Visual Studio 2017. I also have a batch script called foobar.bat that contains the following code:
echo foobar : error 1: This is a test error.
My goal is to get only the test error message above to appear in Visual Studio's Error List when I build a particular project and for the build to stop when it appears. So I put [path to script]\foobar.bat in the project's post-build event command line and then build. Now I'm getting two error messages in the Visual Studio Error List:
The command "[path to script]\foobar.bat" exited with code -1.
This is a test error.
In this case, seeing that first error message that just prints out the contents of my post-build event isn't helpful. I want to suppress this initial error so that only my custom error messages show up in the Error List (or at least change it to say something more useful).
Here's what I've tried:
Adding 2>nul to the end of my batch script has no effect.
Adding 1>nul to the end of my batch script suppresses both errors, which isn't what I want.
Adding &set errorlevel=0 to the end of my batch script has no effect.
Adding the line exit 0 to the end of my batch script has no effect.
Adding the following to the end of my .csproj file (per this article) suppresses the first error, but makes it so the build no longer fails:
<Target
Name="PostBuildEvent"
Condition="'$(PostBuildEvent)'!=''"
DependsOnTargets="$(PostBuildEventDependsOn)">
<Exec WorkingDirectory="$(OutDir)" Command="$(PostBuildEvent)" IgnoreExitCode="true" />
</Target>
The last option almost gets me what I want. However, in spite of there being an error message, the Error List doesn't pop up and the build does not fail. It appears as though anything that would cause the initial error message to not appear will also cause the build to no longer fail. Is that the case? Or is there some way I can get the build to fail without showing that initial error message?
What you can do is use an exec and an error task together.
You need to edit the .csproj file and add these tasks after your the Target PostBuildEvent from your last bullet point above.
This solution works by getting the ExitCode and Output of your exec task and using them to trigger the error task which will then stop the build and log the message.
The Exec task needs three parameters:
IgnoreStandardErrorWarningFormat and IgnoreExitCode prevent the error from being logged at this step
ConsoleToMsBuild parameter is required to get the output (spelled ConsoleToMSBuild in VS 2017).
So the tasks look like this:
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="$(PostBuildEvent)" IgnoreStandardErrorWarningFormat="true" IgnoreExitCode="true" ConsoleToMsBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="OutputMessage" />
<Output TaskParameter="ExitCode" PropertyName="ExitCode" />
</Exec>
<Error Text="$(OutputMessage)" Condition="$(ExitCode) == 10" />
<!-- <Error Text="(optional text) : $(OutputMessage)" Condition="$(ExitCode) == 11" />
<Error Text="(optional text) : $(OutputMessage)" Condition="$(ExitCode) == 12" /> -->
</Target>
And edit the file foobar.bat:
echo foobar : error 1: This is a test error.
exit /b 10 <-- /b parameter needed if used in a .bat file
The important part is the exit that will set the code we want to use afterwards.
You can have more than one Error task do to more conditional logging or just use the output as is.
Re: Adding &set errorlevel=0 to the end of my batch script has no effect.
To ignore the exitcode from a single command use || not & or &&. e.g.
Robocopy || set errorlevel=0
This says only if RoboCopy exits with errorlevel != 0, set errorlevel=0
What does “&&” do in this batch file?]1 explains this and more
Historical Notes
The single ampersand e.g.
(prog1 arg1 arg2) & (cmd2 arg1 arg2 arg3)
runs both commands. It was not very useful in DOS. In Unix, it runs both commands at the same time (2 processes), waiting until both finished. Since DOS did not support multiple-processes the '&' was just syntactic sugar for running sequentially.
The single pipe prog1 | prog2 suffered the same limitations in DOS. In Unix after prog1 writes a modest amount on stdout, it is available to prog2 on its stdin.
In DOS this was shorthand for
prog1 > tmpFile
prog2 < tmpFile
In many cases this worked well enough. In the simple case of write1Meg | head, (or more)
DOS had to run to completion before, head could exit after reading the 1st 10 lines.
What does & do?
Unix also supports & at the end of the command-line
prog1 &
This starts prog1 and returns control to the console quickly.
&& and || only make sense when you know that an exit code of 0 is treated like 'true' and non-zero as 'false'. Also short-circuit evaluation is done, so the second command after checking the exit code of the first.
prog1 && prog2
After prog1 exits, prog2 runs only if exitcode == 0
prog1 || prog2
After prog1 exits prog2 runs only if exitcode != 0
I have a batch file that calls C# program. This C# program makes call to SQL Server database.
Sometimes it is unable to connect to the database and the exception handler prints stack trace and exits c# program. I want to try to run this program maximum of 5 times.
If it succeeds (before 5 tries) then go to next step (CheckStatus) else Error out and quit.
When I run this, It is printing %ERRORLEVEL% as zero even when C# program has an error.
#ECHO OFF
SET Header=-----------------------------------------------------
SET Logfile=C:\LOG\log.txt
set %ERRORLEVEL% = 0
echo %header%
ECHO Running the batch file >> %Logfile%
if '%1' == '' goto usage
if '%2' == '' goto usage
if '%1' == '/?' goto usage
if '%1' == '-?' goto usage
if '%1' == '?' goto usage
if '%1' == '/help' goto usage
SET SQLServer=dbsql\production
SET SQLUser=user1
SET SQLPass=pwd1
SET SQLCommandMaster=osql -S%SQLServer% -n -U%SQLUser% -P%SQLPass% -b -i
GOTO %1%
:Start
Set count=0
:RunCSharpProgram
set /a count+=1
ECHO starting RunCSharpProgram count >> %Logfile%
timeout /t 10
SET RunningStep="RunCSharpProgram"
start "" "C:\CSharpProject\GetData\GetData\bin\Debug\GetData.exe"
ECHO %ERRORLEVEL% >> %Logfile%
IF %ERRORLEVEL% ==1 and count LEQ 5 (GOTO RunCSharpProgram)
IF %ERRORLEVEL% ==1 and count EQ 5 (GOTO error)
IF %ERRORLEVEL% ==0 (GOTO CheckStatus)
:CheckStatus
ECHO Check Status of tables >> %Logfile%
REM %SQLCOMMANDMASTER% /Q "EXEC TestDB.dbo.CheckStatus"
goto end
:usage
echo Usage: %0 'start step' 'end step'
goto end
:error
REM ---------------------------------------------------------------------
ECHO ERROR RUNNING BatchFileTest.BAT >> %Logfile%
:end
echo %header% >> %Logfile%
echo END >> %Logfile%
Not sure what is wrong with this batch file.
Thanks
MR
When you use start, it would start a new shell to run your program.
Official documentation
Starts a separate Command Prompt window to run a specified program or command.
Since it is a separate command prompt you will NOT get back the error codes. So, simple solution do not use the start
instead of
start "" "C:\CSharpProject\GetData\GetData\bin\Debug\GetData.exe"
you can just use
"C:\CSharpProject\GetData\GetData\bin\Debug\GetData.exe"
How do I passt following parameters to my batch file?
custom.bat mode="test" logs="true"
I tried to double the " but nothing helped.
custom.bat "mode="test"" "logs="true""
And, in custom.bat you remove the unneeded quotes
#echo off
set "arg1=%~1"
set "arg2=%~2"
echo [%arg1%] [%arg2%]
You may use CALL command to launch a new batch-file. After executing the last line of the "called file", the control will return back to the "calling file".
You may set the parameters to the "called .bat fie" by using either a simple string or a variable.
eg.
CALL MyScript.bat "1234"
or
SET _MyVar="1234"
CALL MyScript.bat %_MyVar%
As a precaution, you may use SETLOCAL & ENDLOCAL to keep separation between variables of same-name among different files.
Here is my attempt to copy my application executable to another folder changing it's name:
IF $(ConfigurationName) == Release (
SET DESTINATION=$(ProjectDir)Output\Distribution
IF NOT EXIST "%DESTINATION%" ( MD "%DESTINATION%" )
XCOPY /Q /Y "$(TargetPath)" "%DESTINATION%"
RENAME "%DESTINATION%\$(TargetFileName)" "$(TargetName).Plain$(TargetExt)"
)
I've tried everything to make it work, but it always throw error code 255 or 1, it depends. Running that code with a plain batch file works like a charm!
You need to enable delayed expansion, using the SETLOCAL EnableDelayedExpansion command. Do it at the top of the post-build event. After that, you can access your variable by using not %VARIABLE_NAME%, but !VARIABLE_NAME! (use an exclamation symbol on either side of the variable name, not the percentage symbol which you would use in a regular batch file).
So, for example
SETLOCAL EnableDelayedExpansion
IF $(ConfigurationName) == Release (
SET DESTINATION=$(ProjectDir)Output\Distribution
echo My destination dir is !DESTINATION!
)
This will output something like
My destination dir is D:\Work\Projects\PBExample\Output\Distribution.
Since the Post-build event command line actually runs as a batch file you need to escape characters like % by doubling them to %%:
https://stackoverflow.com/a/13552702/74585