Wednesday, February 23, 2011

Mercurial and subversion

I've been using mercurial fairly regularly for most of my hobby projects. Subversion happens to be the VCS of choice at work. In a recent project I was working on I wanted to do some major refactoring in a work related project and instead of the usual approach of creating a branch in subversion I decided to try a new approach, using mercurial and subversion together :). Branching in mercurial is vastly easier than in subversion and the ability to quickly see a graphical branch tree using hg serve is simply priceless. With minimal hgignore and svn:ignore changes mercurial and subversion can be made to mutually ignore each other :D. Heres a simple example
$ mvn archetype:create -DgroupId=test -DartifactId=test -Dversion=1.0 -Dpackaging=jar -Dpackage=test
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:create] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:create {execution: default-cli}]
[WARNING] This goal is deprecated. Please use mvn archetype:generate instead
[INFO] Defaulting package to group ID: test
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: maven-archetype-quickstart:RELEASE
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: test
[INFO] Parameter: packageName, Value: test
[INFO] Parameter: package, Value: test
[INFO] Parameter: artifactId, Value: test
[INFO] Parameter: basedir, Value: f:\shyam\emacs-23\bin
[INFO] Parameter: version, Value: 1.0
[INFO] ********************* End of debug info from resources from generated POM ***********************
[INFO] OldArchetype created in dir: f:\shyam\emacs-23\bin\test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Thu Feb 24 03:15:08 IST 2011
[INFO] Final Memory: 8M/20M
[INFO] ------------------------------------------------------------------------
$ svn add test
A  test/pom.xml
A  test/src
A  test/src/main
A  test/src/main/java
A  test/src/main/java/test
A  test/src/main/java/test/App.java
A  test/src/test
A  test/src/test/java
A  test/src/test/java/test
A  test/src/test/java/test/AppTest.java
$ svn commit -m "adding test"
Adding  test/pom.xml
Adding  test/src
Adding  test/src/main
Adding  test/src/main/java
Adding  test/src/main/java/test
Adding  test/src/main/java/test/App.java
Adding  test/src/test
Adding  test/src/test/java
Adding  test/src/test/java/test
Adding  test/src/test/java/test/AppTest.java
Transmitting file data .
Committed revision 34.
$ cd test
$ svn propset svn:ignore '.hg
.hgignore
.project
.classpath
.settings
target' .
property 'svn:ignore' set on .
$ svn commit -m "setting svn:ignore"
Sending  .
Committed revision 34.
$ hg init
$ cat > .hgignore
syntax: regexp

^target
^.project
^.classpath
^.settings

syntax: glob
.svn
^D
$ hg add
adding .hgignore
adding pom.xml
adding src/main/java/test/App.java
adding src/test/java/test/AppTest.java
$ hg commit -m "initial import"
And, we are all set to go :)

Sunday, February 06, 2011

Subversion links using svn:externals

Recently, I got to play with a really cool feature in subversion. The problem was that 2 components of the same project decided to follow a slightly different project layout, the UI portion decided to go ahead with the default eclipse web project layout while the backend services decided to use maven modules. And, one necessary module was to map the service outputs to the VO's understood by the UI. Since, the UI code was not using maven I decided to introduce a module for the UI VO's to be added as a dependency for the bridge module and was looking around to do it such that any changes in the UI component was also reflected in the service component. After a bit of googling I found the perfect solution using svn:externals. Here is how my svn repo was laid out
/tags
/branches
/trunk/my-project-war
/trunk/my-project-war/src
/trunk/my-project-war/WebContent
/trunk/my-project-war/...
/trunk/my-project-services
/trunk/my-project-services/pom.xml
/trunk/my-project-services/core
/trunk/my-project-services/core/pom.xml
/trunk/my-project-services/...
Here is an abridged version of how I configured it.
$ svn co http://.../trunk/my-project-services services-proj
$ cd services-proj
$ mvn archetype:generate -DgroupId=com... -DartifactId=ui -Dversion=1.0 -Dpackaging=jar -Dpackage=com...
$ cd ui
$ # clean up the default archetype files and create create the parent directories
$ # down to penultimate package level eg. for com.mycompany.project.vo
$ mkdir -p src/main/java/com/mycompany/project
$ # add the ui directory to subversion and do a preliminary commit
$ # drop down to the created directory
$ cd src/main/java/com/mycompany/project
$ # setup svn:externals
$ svn propset svn:externals 'vo ^/trunk/my-project-war/src/com/mycompany/project/vo' .
$ svn commit -m "setting up link to ui project" .
$ svn up
$ # all done :)
Whenever you update or check status of your working copy the linked directory will be displayed with an X
$ cd services-proj/ui/
$ svn st
X services-proj/ui/com/mycompany/project/vo