Wednesday, September 24, 2008

cvs to svn via git

It actually works. The problem: I wanted to take the history of a partial cvs repository into svn. Directly using the tools was out for two points: First, one needs access to the svn repository itself (at least I think so and didn't bother to check because of) second I wanted to patch the paths of the java packages contained therein. Apparently eclipse doesn't quite want to deal with, so it needs to converted to even though the company only owns the former domain.

Anyway, I did not figure out yet how to use git-cvsimport and git-svn both on the same repository sensibly; and I think git-svn rewriting of the commits doesn't quite make that feasible. But the problem already starts with getting both histories to have a common ancestor. Unfortunately git does not have a null commit as the universal base.

Ok, final approach: Create project base directories (the ttb) in svn, do an git svn clone on that. Separately, use git-cvsimport to get the history from cvs into git. (Caveat: The approach does only handle a single linear history well.) Use git format-patch --root commit to get a series of patches, run those through sed -e (which patches directory names as well as imports and package declarations). Then apply (git-am) the resulting commits in the git-svn repository, and git-svn dcommit them. Done.

Except that my link to the svn repository isn't exacly fast at the moment (roundtrip at about a second), and the 60 commits took two hours. svn does not seem to like slow links; a simple tag operation (svn cp trunk tag/some) on a small thingy took me more than a minute over GPRS once.

Here's the complete commands:
mkdir myproj-cvs
cd myproj-cvs
git-cvsimport -p x -v -k -a -d :pserver:krey@localhost:/opt/cvs mystuff/myproj
git-format-patch -o out --root `cat .git/refs/heads/master`
mkdir mod
cd out
for i in *.patch; do sed -e s:company_name:companyname:g $i >../mod/$i; done
cd ../..
svn mkdir http://localhost:4080/repos/mystuff/myproj -m 'base dir'
svn mkdir http://localhost:4080/repos/mystuff/myproj/trunk -m 'trunk dir'
git-svn clone -s http://localhost:4080/repos/mystuff/myproj
cd myproj
git am ~/myproj-cvs/mod/*
git svn dcommit

Monday, September 22, 2008

Inband signalling is evil

In telephone inband signalling is, or rather, was to control circuit setup and teardown by tone signals within the speech band that is also transmitted from speaker to listener. Had the unfortunate effect that you use a specific whistle on the phone and lose the connection. Soon got exploited in more creative ways.

Anyway, in C++'s std::string often the same thing happens. When in C, you have a char*, and you can null it to mark the no value case. Not so in C++. You need a special value, and usually this is the empty string "". Fine and dandy as long as you can be sure that that value will never actually occur. Once this happens all the code will already be riddled with if (val != "") and you never find them all. Bad luck, just like with Y2K.

Neither do you have Maybe, the Haskell way of avoiding null pointer exceptions completely.