Showing posts with label batch file. Show all posts
Showing posts with label batch file. Show all posts

SVN, Hudson & MSBuild - Building code on post commit

SVN, Hudson and MSBuild - Revision control repository
SVN, Hudson and MSBuild - Continuous Integration

This is the third and last installment in the series I’m writing about SVN, Hudson and MSBuild.

Today I’m going to show you the last piece that actually makes the whole thing work. We could call this the plumbing. The piece lies within a specific SVN folder related to your project. It’s called hooks. The path to the hooks folder is this:

Project’s hooks folder before the set upFigure 1 - Project’s hooks folder before the setup

As you can see there are some template files ( .tmpl ). The one we’re going to use to inform Hudson that it’s time to build the code just committed to the repository is the file post.commit.tmpl. Make a copy of this file and change its extension to .bat since it’ll be used by SVN to execute some commands. The file should be named post-commit.bat.

Open the .bat file and add this code at the end:

SET REPOS=%1
SET REV=%2
SET CSCRIPT=C:\WINDOWS\system32\cscript.exe
SET VBSCRIPT=C:\svn\post-commit-hook-hudson.vbs
SET SVNLOOK=C:\Program Files\VisualSVN Server\bin\svnlook.exe
SET HUDSON=http://leniel-pc:8080/
"%CSCRIPT%" "%VBSCRIPT%" "%REPOS%" %REV% "%SVNLOOK%" %HUDSON%

Note above that we’re setting some vars and pointing to some specific files:

- CSCRIPT points to cscript.exe file that should be present in your Windows system32 folder.

- VBSCRIPT points to to the post-commit-hook-hudson.vbs file and its code is as follows:

repos   = WScript.Arguments.Item(0)
rev     = WScript.Arguments.Item(1)
svnlook = WScript.Arguments.Item(2)
hudson  = WScript.Arguments.Item(3)

Set shell = WScript.CreateObject("WScript.Shell")

Set uuidExec = shell.Exec(svnlook & " uuid " & repos)
Do Until uuidExec.StdOut.AtEndOfStream
  uuid = uuidExec.StdOut.ReadLine()
Loop
Wscript.Echo "uuid=" & uuid

Set changedExec = shell.Exec(svnlook & " changed --revision " & rev & " " & repos)
Do Until changedExec.StdOut.AtEndOfStream
  changed = changed + changedExec.StdOut.ReadLine() + Chr(10)
Loop
Wscript.Echo "changed=" & changed

url = hudson + "subversion/" + uuid + "/notifyCommit?rev=" + rev
Wscript.Echo url

Set http = CreateObject("Microsoft.XMLHTTP")
http.open "POST", url, False
http.setRequestHeader "Content-Type", "text/plain;charset=UTF-8"
http.send changed

- SVNLOOK points to svnlook.exe file that comes with VisualSVN Server (see part 1 of this series for more details about it).

- HUDSON points to your Hudson server address. Change it accordingly.

With it all configured we should be ready to get an automatic build when code is committed to the repository.

To test your environment, change any file already versioned and commit it. Open Hudson in your browser and watch a new build start automatically.

If you look in Hudson’s build Console Output you’ll see that the build was initiated by an SCM change.

That’s all!

This is how your SVN project hooks folder should look like now:

Project’s hooks folder after the set upFigure 2 - Project’s hooks folder after the setup

Can you spot another .bat file in the folder? It’s the pre-revprop-change.bat. I’ve been using it so that I can modify the commit’s log message/comment when I forget to mention something or to correct spelling. More info about this file can be seen in this StackOverflow question: What is a pre-revprop-change hook in SVN and how do I create it?

Programming-Constructing a Batch file

Batch file
In MS-DOS, OS/2, and Windows, a batch file is a text file containing a series of commands intended to be executed by the command interpreter. When a batch file is run, the shell program (usually COMMAND.COM or cmd.exe) reads the file and executes its commands, normally line-by-line. Batch files are useful for running a sequence of executables automatically and are often used by system administrators to automate tedious processes.

For more details, see the Batch file document at Wikipedia.

A sample batch file
In a recent post titled Syntactic Analyzer built with Flex and YACC I used a simple batch file in the compilers construction paper. Why I did that? To avoid boiler plate work while executing the commands necessary to generate the syntactic analyzer executable.

In this post I'll present and comment in more details the content of such batch file.

The following table shows the content of the batch file. I also include the command line number and its respective comment in the table, so that it's easier to visualize what's going on.

# Code Comment
1 @Echo Off Turn off screen messages
2 ::cls A comment. Start with ::
3 :Start Declare the label Start
4 Echo. Print a blank line. See the dot after Echo.
5 Echo Batch file Menu Print the string "Batch file Menu"
6 Echo. Print a blank line
7 Echo 1 - MinGW Print the string "1 - MinGW"
8 Echo. Print a blank line
9 Echo 2 - SinAn Print the string "2 - SinAn"
10 Echo. Print a blank line
11 Echo 3 - Exit Print the string "3 - Exit"
12 Echo. Print a blank line
13 set choice= Declare the choice variable
14 set /p choice=Choice: See note 1.
15 if not '%choice%'=='' set choice=%choice:~0,1% See note 2.
16 if '%choice%'=='1' goto MinGW Go to label MinGW at line 22
17 if '%choice%'=='2' goto SinAn Go to label SinAn at line 25
18 if '%choice%'=='3' goto Exit Go to label Exit at line 37
19 Echo "%choice%" is not valid. Prints error if choice isn't 1, 2 or 3
20 Echo. Print a blank line
21 goto Start Go to label Start at line #3
22 :MinGW Declare the label MinGW
23 path=C:\MinGW\bin;%PATH% Rewrite path with new value. See note 3.
24 goto end Go to label end at line 39
25 :SinAn Declare the label SinAn
26 @Echo On Turn on screen messages
27 path=C:\MinGW\bin;%PATH% Rewrite path with new value
28 cls Clear the screen
29 CD CompCons Navigate to CompCons directory
30 flex -i lexan.lex Execute flex command
31 yacc sinan.yacc Execute yacc command
32 gcc y.tab.c yyerror.c main.c -osinan -lfl Execute gcc command
33 sinan <factorial.txt Execute sinan command. See note 4.
34 cd.. Navigate one directory above
35 @Echo Off Turn off screen messages
36 goto end Go to label end at line 39
37 :Exit Declare the label Exit
38 goto end Go to label end at line 39
39 :end Declare the label end. EOF :)

Notes
There are four notes that I think are worth commenting:

  1. set /p choice=Choice:
    The /p switch tells the command interpreter that the value of the variable choice will be the input entered by the user. The interpreter will display the string "Choice:" before reading the line of input.
    This command has the following format: set /p variable=[promptString]
  2. if not '%choice%'=='' set choice=%choice:~0,1%
    Every time you need to get the content of a variable it's necessary to enclose it with the percent sign %. Note the use of the quotation mark in both sides too. If a command contains two percent signs, the command interpreter will treat any characters between them as an environment variable to be expanded.
    The tilde sign ~ tells the interpreter that I want to slice a string in a variable.
    This command has the following format: %NAME:~s,n where s is the start position (zero-offset) and n is the number of characters. If s is negative, then the offset starts from the right side minus 1 (i.e. -1 refers to the rightmost character). If n is negative, then length -n characters, are extracted.
    If the variable choice isn't empty, get only the first character of the user input.
  3. path=C:\MinGW\bin;%PATH%
    The path variable is already part of the operating system set of variables. In this case I'm just rewriting its value with the desired directory. Note that I also attribute to path the content of other defined variable called PATH.
  4. sinan < factorial.txt
    Having no to do with the batch file explanation and just for the sake of clarification: the less angle bracket symbol < means that I'm redirecting the contents of the file factorial.txt to the executable file sinan. The sinan executable will consume the data stored in the factorial.txt file to do its computations.

To execute a batch file, just open a command prompt and type its name. You can even type the name without the .bat extension.

When a batch file is executed, the command interpreter will automatically execute each line of the batch file automating the whole process, that is, you won't need to type the same series of commands each time you want to execute a single work.

In this sample batch file what I want to accomplish is to run 4 executable files - see lines 30, 31, 32 and 33. By selecting option 2 at line 17, the interpreter goes to line 25 and so I'll have all the 4 executables running with a single command since the SinAn label at line 25 comprises these commands.

You can get the sample batch file at: http://leniel.googlepages.com/SampleBatchFile.bat