Branch/Tag multiple repos (SubVersion)
Continuous Integration March 9th, 2009For our product we have several repos that all need to be branched when releasing a stable version. Manually doing this takes a lot of time and because of that I created an ant-script that does this. There are four main public targets and four main private targets:
A public target to create branches and a private to create one branch.
A public target to create tags and a private to create one tag.
A public target to delete branches and a private to delete one branch.
A public target to delete tags and a private to delete one tag.
Important parameters that need to be defined (can be done using ant-form, in a properties file or in the main ant file):
cvsdude.repository.branch.name : Name of the branch to create or delete in each of the repositories.
cvsdude.repository.tag.name : Name of the tag to create or delete in each of the repositories.
cvsdude.repository.user : Username for credentials repository.
cvsdude.repository.passwd : Password for credentials repository.
repos : Comma seperated list of the url's of repositories.
Create Branches
-
<!-- Creates a Branch -->
-
<!-- @param currentUrl Url of repo -->
-
<!-- @param cvsdude.repository.branch.name Name of the Branch -->
-
<!-- @param cvsdude.repository.user Username (credentials repository) -->
-
<!-- @param cvsdude.repository.passwd Password (credentials repository) -->
-
<target name="create-branch" xmlns:ac="http://antcontrib.sf.net">
-
<ac:trycatch>
-
<try>
-
<echo level="info">Branching ${currentUrl}</echo>
-
<svn username="${cvsdude.repository.user}" password="${cvsdude.repository.passwd}">
-
<copy srcUrl="${currentUrl}/trunk" revision="HEAD"
-
destUrl="${currentUrl}/branches/${cvsdude.repository.branch.name}"
-
message="Branching Edumatic3 ${timeStamp}"/>
-
</svn>
-
</try>
-
<catch>
-
<echo> Failed Deleting Branch ${currentUrl}</echo>
-
</catch>
-
<finally>
-
</finally>
-
</ac:trycatch>
-
</target>
-
-
<!-- Creates Branches for all repos in ${repos} -->
-
<!-- @param ${cvsdude.repository.branch.name} Holds name of Branch -->
-
<!-- @param ${repos} Comma seperated list of repositories -->
-
<target name="create-branches" xmlns:ac="http://antcontrib.sf.net">
-
-
<echo message="create-branches"/>
-
<echo message="Name branch: ${cvsdude.repository.branch.name}"/>
-
<echo message="repos:${repos}"/>
-
-
<ac:for list="${repos}" param="currentRepo" trim="true">
-
<sequential>
-
<antcall target="create-branch">
-
<param name="currentUrl" value="@{currentRepo}"/>
-
</antcall>
-
</sequential>
-
</ac:for>
-
</target>
Delete Branches
-
<!-- Deletes a Branch -->
-
<!-- @param currentUrl Url of repo -->
-
<!-- @param cvsdude.repository.branch.name Name of the Branch -->
-
<!-- @param cvsdude.repository.user Username (credentials repository) -->
-
<!-- @param cvsdude.repository.passwd Password (credentials repository) -->
-
<target name="delete-branch" xmlns:ac="http://antcontrib.sf.net">
-
<ac:trycatch>
-
<try>
-
<echo level="info">Deleting Branch ${currentUrl}</echo>
-
<svn username="${cvsdude.repository.user}" password="${cvsdude.repository.passwd}">
-
<delete url="${currentUrl}/branches/${cvsdude.repository.branch.name}"
-
message="Deleting Branch ${cvsdude.repository.branch.name}"/>
-
</svn>
-
</try>
-
<catch>
-
<echo> Failed Deleting Branch ${currentUrl}</echo>
-
</catch>
-
<finally>
-
</finally>
-
</ac:trycatch>
-
</target>
-
-
<!-- Deletes Branches for all repos in ${repos} -->
-
<!-- @param ${cvsdude.repository.branch.name} Holds name of Branch -->
-
<!-- @param ${repos} Comma seperated list of repositories -->
-
<target name="delete-branches" xmlns:ac="http://antcontrib.sf.net">
-
<echo message="delete-branches"/>
-
<echo message="Name branch: ${cvsdude.repository.branch.name}"/>
-
-
<ac:for list="${repos}" param="currentRepo" trim="true">
-
<sequential>
-
<antcall target="delete-branch">
-
<param name="currentUrl" value="@{currentRepo}"/>
-
</antcall>
-
</sequential>
-
</ac:for>
-
</target>
Create Tags
-
<!-- Creates a Tag -->
-
<!-- @param currentUrl Url of repo -->
-
<!-- @param cvsdude.repository.tag.name Name of the Tag -->
-
<!-- @param cvsdude.repository.user Username (credentials repository) -->
-
<!-- @param cvsdude.repository.passwd Password (credentials repository) -->
-
<target name="create-tag" xmlns:ac="http://antcontrib.sf.net">
-
<ac:trycatch>
-
<try>
-
<echo level="info">Tagging ${currentUrl}</echo>
-
<svn username="${cvsdude.repository.user}" password="${cvsdude.repository.passwd}">
-
<copy srcUrl="${currentUrl}/trunk" revision="HEAD"
-
destUrl="${currentUrl}/tags/${cvsdude.repository.branch.name}"
-
message="Branching Edumatic3 ${timeStamp}"/>
-
</svn>
-
</try>
-
<catch>
-
<echo> Failed Deleting Tag ${currentUrl}</echo>
-
</catch>
-
<finally>
-
</finally>
-
</ac:trycatch>
-
</target>
-
-
<!-- Creates Tags for all repos in ${repos} -->
-
<!-- @param ${cvsdude.repository.tag.name} Holds name of Tag -->
-
<!-- @param ${repos} Comma seperated list of repositories -->
-
<target name="create-tags" xmlns:ac="http://antcontrib.sf.net">
-
<echo message="create-tags"/>
-
<echo message="Name tag: ${cvsdude.repository.tag.name}"/>
-
-
<ac:for list="${repos}" param="currentRepo" trim="true">
-
<sequential>
-
<antcall target="create-tag">
-
<param name="currentUrl" value="@{currentRepo}"/>
-
</antcall>
-
</sequential>
-
</ac:for>
-
</target>
Delete Tags
-
<!-- Deletes a Tag -->
-
<!-- @param currentUrl Url of repo -->
-
<!-- @param cvsdude.repository.tag.name Name of the Tag -->
-
<!-- @param cvsdude.repository.user Username (credentials repository) -->
-
<!-- @param cvsdude.repository.passwd Password (credentials repository) -->
-
<target name="delete-tag" xmlns:ac="http://antcontrib.sf.net">
-
<ac:trycatch>
-
<try>
-
<echo level="info">Deleting Tag ${currentUrl}</echo>
-
<svn username="${cvsdude.repository.user}" password="${cvsdude.repository.passwd}">
-
<delete url="${currentUrl}/tags/${cvsdude.repository.branch.name}"
-
message="Deleting Tag ${cvsdude.repository.branch.name}"/>
-
</svn>
-
</try>
-
<catch>
-
<echo> Failed Deleting Tag ${currentUrl}</echo>
-
</catch>
-
<finally>
-
</finally>
-
</ac:trycatch>
-
</target>
-
-
<!-- Delete Tags for all repos in ${repos} -->
-
<!-- ${cvsdude.repository.tag.name} holds name of Tag -->
-
<!-- @param ${repos} Comma seperated list of repositories -->
-
<target name="delete-tags" xmlns:ac="http://antcontrib.sf.net">
-
<echo message="delete-tags"/>
-
<echo message="Name tag: ${cvsdude.repository.tag.name}"/>
-
-
<ac:for list="${repos}" param="currentRepo" trim="true">
-
<sequential>
-
<antcall target="delete-tag">
-
<param name="currentUrl" value="@{currentRepo}"/>
-
</antcall>
-
</sequential>
-
</ac:for>
-
</target>
I guess that some things can be made more generic and put in macros as lot of logic is duplicated.... But this should get you going.
The libraries you need are svnant and ant-contrib.
thx, Lieven Cardoen
Recent Comments