Thursday, 8 October 2009

copy-merge in ClearCase (on Windows)

For various reasons, there are occasions when you want to merge exactly what has been changed on a branch to another without having ClearCase trying to perform the merge itself. A common issue is for binary elements, but I use it for deliveries as well: an identical copy of the element is "merged" from development to integration.

The solutions I've seen (for example from IBM) aren't satisfactory since they perform the operation on every element, disregarding if they need merging or not. I want to have traceability so that only the files needed are merged, allowing me to easily find what changes have been done between merges.

Here's my solution, made as an MS-DOS batch. Note that it's currently only working for snapshot views, since this was one of my requirements. It should be easy to adapt for dynamic views as well (I might just do that in a "near future" myself).

:: Clear previous mergeset
if exist %MERGESET% del /q %MERGESET%

::Automatically merge all directories
cleartool findmerge . -type d -fversion %VERSION% -merge -nc -log NUL

:: Find items eligible to merge, check these out and record them to file
echo Finding files to merge...
cleartool findmerge . -type f -fversion %VERSION% -log NUL -co -nc -exec "cmd /v:on /c echo !CLEARCASE_FXPN!;!CLEARCASE_PN! >>%MERGESET%"

:: Delete the target
echo Deleting targets...
for /f "tokens=2 delims=;" %%a in (%MERGESET%) do del /q "%%a"

:: Use cleartool get to copy contents from source
echo Copying from source to target...
for /f "tokens=1,2 delims=;" %%a in (%MERGESET%) do cleartool get -to "%%b" "%%a"
for /f "tokens=2 delims=;" %%a in (%MERGESET%) do attrib -R "%%a"

:: Create a merge arrow for the these items
echo Creating Merge arrows...
for /f "tokens=1,2 delims=;" %%a in (%MERGESET%) do cleartool mkhlink -unidir Merge "%%a" "%%b"
Some explanation needed: the %VERSION% is an input parameter holding the exact version merging from (e.g. /main/dev_branch/LATEST).

One "tough nut" for me was to find the /v:on-flag for calling cmd, in conjunction with the !-signs around environment variables. This is what makes them set at runtime, and not at time of calling the script (when it's empty).

Wednesday, 7 October 2009

MS-DOS Parameter handling

Configuration Management involves a lot of scripting, in the OS used by the system. Unfortunately for Windows systems, this means scripting in MS-DOS. Yes, I know of Powershell, but as long as that's not default part of OS (comes with Windows 7) it remains not being a real alternative.

Parameter handling in MS-DOS is weak by default, so here's a routine I stole from an old colleague (Jimmy, if you ever read this, pleas shut up. And I guess you stole it from someone first! ;)

First, set up the internal variables needed. The first gets the dir the script is run from, the second the name of the script:
set BASEDIR=%~dp0
set BASENAME=%~n0
I put the Usage-description early so it's easily readable within the script. Note the ^-signs to allow special chars within echo:
goto GET_PARAMETERS

:USAGE
echo Usage:
echo %BASENAME% ^/f ^ /v
echo    ^/f file : enter file with full path
echo    ^/v      : verbose mode
goto END
Start of parameter loop, with a label. I always put the "help"-flag first out of convenience:
:GET_PARAMETERS

:HELP
if /i [%1] neq [/?] goto FILE
goto USAGE
For each parameter, enter a block in the following way. Check first parameter for the current flag, if found then set a variable and "shift out" from parameter stack and start over. If not found, go to next parameter.
:FILE
if /i [%1] neq [/f] goto VERBOSE
set FILE=%2
shift
shift
goto GET_PARAMETERS
If the parameter is a flag only like in the following case, only one shift is needed:
:VERBOSE
if /i [%1] neq [/v] goto ENDPARAM
set VERBOSE=1
shift
goto GET_PARAMETERS

End of parameter loop, check for any other parameters that aren't covered above and give error message if found:
:ENDPARAM
if [%1] equ [] goto VALIDATE_PARAMETERS
echo Error! Incorrect parameters given
goto USAGE
Validate parameters that are mandatory:
:VALIDATE_PARAMETERS
:: Check for mandatory parameters
if /i [%FILE%] neq [] goto EXECUTION
echo Error! Missing parameter Version
goto USAGE
Start the actual script (finally!). Don't forget the end-label at bottom:
:EXECUTION
...
:END
What does this give you? Well, most importantly you don't need to enter parameters in any order and you only allow prescripted input. As a bonus, you get help and usage description.

If you think it's awkwars, all I can say is that MS-DOS is awkward to script in ;).

Here's the script in one go, for easy copy-paste:

set BASEDIR=%~dp0
set BASENAME=%~n0
 
goto GET_PARAMETERS

:USAGE
echo Usage:
echo %BASENAME% ^/f ^ /v
echo ^/f file : enter file with full path
echo ^/v : verbose mode
goto END

:GET_PARAMETERS

:HELP
if /i [%1] neq [/?] goto FILE
goto USAGE

:FILE
if /i [%1] neq [/f] goto VERBOSE
set FILE=%2
shift
shift
goto GET_PARAMETERS

:VERBOSE
if /i [%1] neq [/v] goto ENDPARAM
set VERBOSE=1
shift
goto GET_PARAMETERS

:ENDPARAM
if [%1] equ [] goto VALIDATE_PARAMETERS
echo Error! Incorrect parameters given
goto USAGE

:VALIDATE_PARAMETERS
:: Check for mandatory parameters
if /i [%FILE%] neq [] goto EXECUTION
echo Error! Missing parameter Version
goto USAGE

:EXECUTION
...
:END