Create branches with Maven Release Plugin (SVN)

I’m currently working on Azure and web packaging (MSDeploy) support for NPanday. I want to do that on a separate SVN branch, which I’ll then reintegrate later on.

The current trunk version is 1.4.1-incubating-SNAPSHOT, and since we are about to release that upcoming version 1.4.1-incubating soon, I don’t want to pollute it with half-baked changes, while I’ll still need to develop on the trunk in parallel.

I’ll also need to be able to install both the current trunk and my experimental branch in my local Maven repository at the same time, hence I need a new temporary version for my branch. All this can be achieved using the Maven Release Plugin, in particular the branch goal. Maven Release supports 14 SCMs through the same interface; in this case we use SVN, though.

What I want

How-to

The command I need to run

mvn release:branch 
   -DbranchName=1.5.0-azuresupport
   -DautoVersionSubmodules=true
   -DsuppressCommitBeforeBranch=true 
   -DremoteTagging=false 
   -DupdateBranchVersions=true 
   -DupdateWorkingCopyVersions=false 

Lets go through the settings line-by-line:

mvn release:branch

Loads and executes the branch-goal from the Maven Release Plugin.

-DbranchName=1.5.0-azuresupport

The name for the branch to be created. When on trunk, Maven figures out to use the default SVN layout for branches and tags. You can optionally define the branch base using the parameter branchBase like this: –DbranchBase=https://svn.apache.org/repos/asf/incubator/npanday/branches/

-DautoVersionSubmodules=true

When ran, Maven will prompt for the version to be used in the branch. I provided 1.5.0-azuresupport-SNAPSHOT. Since autoVersionSubmodules is set to true, Maven Release will automatically use this versions for all submodules and hence also update all inner-project dependencies to that version.

The next four settings go hand-in-hand.

-DsuppressCommitBeforeBranch=true

By default, Maven Releases creates intermediate commits to the current working copy. I’m not sure of the reason, but I think it was because some VCS do not support branching/tagging of modified working copies. This parameter makes sure, no intermediate commits are made to the working copy.

-DremoteTagging=false

With SVN, by default, tags are created remotely. If you want to ommit intermediate commits, this must be set to false.

-DupdateBranchVersions=true

-DupdateWorkingCopyVersions=false

When branching, you can either define new versions for the current working copy, or the new branch, or both. As set here, the working copy will be left alone, and the plugin will ask for a new version for the branch.

Now I can switch forth and back between the trunk and the new branch, but still build and deploy artifacts side-by-side.

Defaults in POM

You may also provide the fixed values in the POM. And if you want to avoid interfering with other Maven Release actions, you might want to use a profile.

<profile>
  <id>branch</id>
  <activation>
    <property>
      <name>branchName</name>
    </property>
  </activation>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.2.1</version>
        <configuration>
          <branchBase>https://svn.apache.org/repos/asf/incubator/npanday/branches</branchBase>
          <autoVersionSubmodules>true</autoVersionSubmodules>
          <suppressCommitBeforeBranch>true</suppressCommitBeforeBranch>
          <remoteTagging>false</remoteTagging>
          <updateBranchVersions>true</updateBranchVersions>
          <updateWorkingCopyVersions>false</updateWorkingCopyVersions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</profile>

Now it will be enough, when I run mvn release:branch –DbranchName=1.5.0-azuresupport

Advertisement

How-to branch and patch SVN- or TFS/Codeplex-based open source projects with GIT (Part 1)

The last couple of weeks I worked a lot with NPanday which brings maven to .NET. But this post is not about NPanday but rather about the workflow for maintaining a personal branch and uploading patches.

I’m not a committer, but I had to do some changes to NPanday. I still want to version my changes. I also want to contribute patches, when I fix bugs that apply to the current trunk.

NPanday is hosted on Codeplex, and though accessible via the SvnBridge. So I chose to give git svn a try.

I also want to host my changes on github.

The Workflow

  • Once
    • Clone a svn repo to a local-git
    • Create a branch for svn updates, say codeplex
    • Create a GitHub repo and push both branches
  • Repeatedly
    • Do your work on master
    • Commit and push your work
    • Update codeplex from subversion and push it
    • Merge codeplex to master
  • Contribute and Commit
    • How to create and submit patches from our master
    • How to commit changes back to codeplex

The How-To

I don’t want to mess around with npanday, so I created a empty test-project on codeplex.: [SAMPLE PROJECT] Branch and Patch with GIT

Setup (Windows)

On mac you simply use mac ports, on linux I have no clue.

  • Install SVN binaries and add to %PATH% (download)

  • The binary mysys doesn’t come with git svn anymore, so you have to compile it yourself. Is not as hard as it sounds. Just download the fullinstall – it will run the compile for you. (download 1.7.0.2 , downloads) Don’t forget to add it to the path, too.

I’ll do everything on the command line. Red is SVN, green is GIT – they are in separate folders.

I use pictures. Type it yourself! It will help you to learn it.

Don’t be afraid reading the command line either. It’s like code! You’ll get used to it, so did I.

Once

Checkout and commit a text fileimage

Init and fetch the commited revision using svn git:

image

Now, since we want to do changes, lets create a branch codeplex but remain on master and do changes.

image 

We should make sure, that the branch codeplex is untouched:

image

I also created a project on github. So lets push it over there. Read how to setup your private key and connect here.

image

Now we have the two commits on the master:

tmp2E0B

And only one on codeplex:

tmpE826

Now we change our “subversion”-file:

image

And then we update it using git svn rebase on the codeplex branch. Sorry for not having accepted the certificate before. But its live! 🙂

image Result:

tmpD8EB

Now we want to have that change over on our work branch.

image

Voilá:

tmpF6A9

Now, this is our repo:

image

Enough for today. Let’s se what we covered:

Recap

  • Once
    • We initialized the empty codeplex repo with a single-line file.
    • Clone a svn repo to a local-git
      We used git svn init and fetch to get the codeplex contents in a local git repository.
    • Create a branch for svn updates, say codeplex
      We created the branch
    • Create a GitHub repo and push both branches
      We pushed both master and codeplex
  • Repeatedly
    • Do your work on master
      We added a file to our master.
    • Commit and push your work
      We pushed it to master. Both the source svn and codeplex branch remain untouched.
    • Update codeplex from subversion and push it
      We added a line and checked it into svn and then we got it into our codeplex branch did that.
    • Merge codeplex to master
      We did that too.

More soon! Probably next Friday:

  • Contribute and Commit
    • How to create and submit patches from our master
    • How to commit changes back to codeplex

Setting svn:keywords for specific files with Windows Powershell – Or grep with Powershell

In one of my current projects, all source files need to have a file-header looking like this:

// -------------------------------------------------------------
// <copyright company="..." file="Variance.cs">
//   ...
// </copyright>
// <remarks>
//   $HeadURL: https://svn....Api/Utils/Variance.cs $
//   $LastChangedRevision: 1951 $
//   $LastChangedDate: 2009-07-21 $
//   $LastChangedBy: corn_la $
// </remarks>
// <summary>
//   Safe co- and contra-variance for Interfaces in .NET FW 3.5.
// </summary>
// -------------------------------------------------------------

But all to often, the remarks part of the header is uncomplete:

// <remarks>
//   $HeadURL$
//   $LastChangedRevision$
//   $LastChangedDate$
//   $LastChangedBy$
// </remarks>

This means, someone (mostly me) checked in a file with out having configured the svn-keywords property properly.

Now, with “svn propset –R ….” you can reset the properties on all files in a directory recursively. But this is not smart enough to recognize if the properties really changed or not. So it would touch all files specified and boom, every header changes.

What I want to do is setting the properties only on those files that have no properties defined.

Good reason for learning Windows Power Shell! 🙂

Well, here is the command I used:

gci . -r -i *.cs | ? { (gc $_.fullname) -match '\$HeadURL\$$' } | % { svn ps svn:keywords "HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.fullname }

It uses a lot of aliases. The full version would look like this:

Get-ChildItem . -Recurse -Include *.cs 
    | Where-Object { 
        (Get-Content $_.FullName) -match '\$HeadURL\$$'
      } 
    | ForEach-Object { 
        svn propset svn:keywords "
HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.FullName 
      }

And here is, what it does:

  1. Getting FileInfos for all C#-files recursively in the current directory
  2. Selecting those FileInfos, where the content has a line ending on “$HeadURL$”, which means there was no property set for HeadURL. Getting and comparing the svn props was even slower 🙂
  3. Calling  “svn propset” on every FileInfo-Object using the FullName as command line argument

Issues:

  • It was very hard to find good documentation on PowerShell!!
  • Hard to find how to use regex with power shell. The problem was finding the dollar sign, because it is used for variable usage in double quoted strings. It only works properly in single-quoted strings.

    More on regex with powershell
  • It took me a while to find the aliases ?  and % for where-object and foreach-object. Again, hard to find documentation.

Many thanks to Johannes Rössel for helping me with PowerShell on a stackoverflow-Question.

Setting svn:keywords for specific files with Windows Powershell – Or grep with Powershell

In one of my current projects, all source files need to have a file-header looking like this:

// -------------------------------------------------------------
// <copyright company="..." file="Variance.cs">
//   ...
// </copyright>
// <remarks>
//   $HeadURL: https://svn....Api/Utils/Variance.cs $
//   $LastChangedRevision: 1951 $
//   $LastChangedDate: 2009-07-21 $
//   $LastChangedBy: corn_la $
// </remarks>
// <summary>
//   Safe co- and contra-variance for Interfaces in .NET FW 3.5.
// </summary>
// -------------------------------------------------------------

But all to often, the remarks part of the header is uncomplete:

// <remarks>
//   $HeadURL$
//   $LastChangedRevision$
//   $LastChangedDate$
//   $LastChangedBy$
// </remarks>

This means, someone (mostly me) checked in a file with out having configured the svn-keywords property properly.

Now, with “svn propset –R ….” you can reset the properties on all files in a directory recursively. But this is not smart enough to recognize if the properties really changed or not. So it would touch all files specified and boom, every header changes.

What I want to do is setting the properties only on those files that have no properties defined.

Good reason for learning Windows Power Shell! 🙂

Well, here is the command I used:

gci . -r -i *.cs | ? { (gc $_.fullname) -match '\$HeadURL\$$' } | % { svn ps svn:keywords "
HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.fullname }

It uses a lot of aliases. The full version would look like this:

Get-ChildItem . -Recurse -Include *.cs 
    | Where-Object { 
        (Get-Content $_.FullName) -match '\$HeadURL\$$'
      } 
    | ForEach-Object { 
        svn propset svn:keywords "
HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.FullName 
      }

And here is, what it does:

  1. Getting FileInfos for all C#-files recursively in the current directory
  2. Selecting those FileInfos, where the content has a line ending on “$HeadURL$”, which means there was no property set for HeadURL. Getting and comparing the svn props was even slower 🙂
  3. Calling  “svn propset” on every FileInfo-Object using the FullName as command line argument

Issues:

  • It was very hard to find good documentation on PowerShell!!
  • Hard to find how to use regex with power shell. The problem was finding the dollar sign, because it is used for variable usage in double quoted strings. It only works properly in single-quoted strings.

    More on regex with powershell
  • It took me a while to find the aliases ?  and % for where-object and foreach-object. Again, hard to find documentation.

Many thanks to Johannes Rössel for helping me with PowerShell on a stackoverflow-Question.