Archive for the ‘Tools’ Category

Report on git

Tuesday, June 19th, 2007

After seeing this video of Linus Torvalds waxing arrogant about git, the source code management system he wrote for Linux kernel development, I decided I should try it out.

The benefits of git over the CVS/Subversion model amount to this: (1) git is distributed, and (2) git is fast. (2) is partly a result of (1), partly a result of Linus being a wizard programmer.

For git, “distributed” means that every working directory is a full-fledged repository in its own right. That is, there is no single repository that all developers check out of and commit into. Commits are done locally, into your own copy of the repository. Sharing is done only explicitly, so nobody can screw up your personal copy of the code with their code, and vice versa. Distribution also gets you a bunch of speed, because commits are simply written into your local filesystem. Beyond that, Linus used a lot of fancy impressive algorithms to make things generally fast.

I used Fink to install git on my OS X machines (it’s in the unstable tree), and found that it works pretty much as advertised. The tutorial at kernel.org is quite nice; below is a quick summary of the most important things I gleaned from it.

Installation

On Mac OS X, you need to install Fink if you don’t have it. Then add unstable/main and unstable/crypto to /sw/etc/fink.conf, and then do

fink selfupdate; fink index; fink scanpackages

to activate the unstable trees.

Then do

fink install git

and type your admin password when it’s asked for.

On Linux, it’s probably just a matter of installing it from whatever package manager your distro has.

User Configuration

For the sake of the logs, you should first configure git to know your name and email address:

git config --global user.name "Ed Baskerville"
git config --global user.email notmyemailaddress@edbaskerville.com

Creating a Repository

To make a new repository from scratch and start working on it, you create the working directory and cd into it, create the repository inside, and then check out the empty main branch:

mkdir myproj
cd myproj
git-init
git-checkout

Notice I didn’t specify any arguments to init or checkout. Init assumes you want to create a repository called .git inside the current directory, and checkout assumes you want to check out code from .git into the current directory to begin working. So the standard directory structure is this:

myproj/ [the working directory]
    .git/ [the repository directory]
        ...
        [the git repository's internal state]
        ...
    ...
    [working source files]
    ...

Cloning a Repository

If there’s an existing repository that you want a copy of, you don’t check out a working copy as with CVS/Subversion. Rather, you clone it, making a copy of the complete repository for yourself. This works from a local file, via ssh, via http, or through git-daemon, which needs to be installed on the “server” machine. Examples:

git clone /local/path
git clone ssh://server.name/remote/path
git clone http://www.kernel.org/pub/scm/git/git.git
git clone git://git.sv.gnu.org/lilypond.git

Making Changes

Making and committing changes is pretty much just like CVS or Subversion: you edit or add files in your working directory, and then commit them, only your commits go into the local repository .git repository directory.

So you could create a file called myprogram.c:

echo I bet this won't compile > myprogram.c
git add myprogram.c
git commit

One catch is that you need to do a git add before a commit for all files that have changed, not just files that are new. You can get around this with the -a switch:

git commit -a

will first add any files that have changed to the commit (but not new files that have been created—they must be added explicitly) and then commit.

Pulling and Pushing

Source code management isn’t much use unless you can share your work. If somebody else has changes you want to merge into your copy of the repository, use git pull:

git-pull /path/to/repository

If you’re operating on a CVS/Subversion-like model with a central master repository, push can be used to put your changes into that repository:

git-push ssh://server.name/path/to/repository

Branches

I won’t spend time on branching, but one of the key reasons to use git is that branches are cheap and easy, so you can easily split off experimental branches to do things that might fail spectacularly. The tutorial has good information about all this.

EcoGillespie + Eclipe + JUnit = Java Is Fun!

Wednesday, May 17th, 2006

Why/Why Not Java

I’ve had an on-again, off-again relationship with Java. It always appealed to me: it runs on every platform without modification (particularly if you’re not dealing with a GUI); since the invention of JIT compilers, it’s basically as fast as C/C++, and faster than Objective-C; and its syntax is like C++, only way less convoluted.

Still, a couple years ago, I probably wouldn’t have decided to do EcoGillespie in Java. Back then, Java had this weird hybrid between static and dynamic typing. Where this caused me trouble was with collections, primarily: you could put any kind of object you wanted into a collection (good general feature of collections!) but, because the Java compiler enforces type-checking strongly, when you pulled that object out of the collection, you had to manually cast it to the correct type. (The “correct” way to do something like that is to actually CHECK its type using the instanceof operator when you pull it out of the collection. But I’m talking about cases where you NEVER put anything other than one type of object into a particular collection.) In C++, there’s this abomination called templates, where the compiler automatically generates an entirely new class whenever you have a collection with a parameterized type.

C# added this nice thing called generics that’s the best of both worlds. Like Java collections, there’s just one class for all types of objects; like C++ template collections, instances are tied to parameterized types. The improvement on Java is that you have type parameterization, so you can specify at compile time what kind of objects are going into (and thus coming out of) your collections. But you do this without generating new classes for each parameterized collection type—rather, the parameters are set *per instance*.

The Java guys thought this was a good idea too, so it has made an appearance in the 1.5/5.0 release of Java (code-named Tiger, a name no doubt picked in order to cause confusion with Mac OS X 10.4).

There are bunch more features that make life easier: autoboxing (automatic conversion of primitive types like int and double to object types like Integer and Double), automatically iterating for loops (for object : collection rather than the full iterator rigamarole), and some others.

That was a long rant not really relevant to the meat of this post. The point is, I like Java way, way more now than I did. I don’t mind that generics work a little hackishly at the compiler level, for reasons of backward-compatibility: since I’m writing all new JDK 1.5/5.0/whatever the hell they’re calling it now code, I don’t have to worry.

The Wonder of Eclipse

I had heard about this free thing called Eclipse that’s all the rage these days, so I downloaded it and tried it out. At first I was confused—too many things going on! But after working with it for about a day, getting to know its way of thinking, I really like it. I’m particularly loving its refactoring features. Say I decide a method should be named something else, or have parameters in a different order: I just right-click, choose something from the Refactor submenu, tell it what I want, and not only does the method get fixed up, but every call to the method anywhere in the project gets fixed as well. Sure beats a manual find/replace, even if you’re comfortable with regular expressions (which I am ashamed to say are not second nature to me yet). Syntax coloring, completion, etc., etc., all nice.

One thing that annoys me: you can’t pop subviews of the window out into separate windows. You can create a new full environment window and do things that way, but I’d prefer being able to just drag a view out of the main window and have it magically turn into a single-function mini-window that logically behaves as a child of the main window. I like the one-window approach in general, but I like to be able to break things out across multiple monitors when I need to.

The only other annoyance is that completion doesn’t know the names to parameters (it calls them arg0, arg1, etc.)—they should integrate it with Javadoc and not just the class bytecode so this is smarter.

JUnit

I have also been hearing the joys of unit testing trumpeted for many years, but, being lazy and never working on mission-critical code, I never got around to using that methodology myself. Well, I read up on JUnit today and put in unit tests for the ParameterMap class in EcoGillespie, and, what can I say, it’s wonderful. For a modest increase in programming time, testing time will be greatly reduced, and test coverage will be way better. Furthermore, it just makes you write better code to write the tests first: your brain is forced to concentrate on the edge cases, as well as the usability of your classes, from the very beginning. Wunderbar.

Oh, and it integrates beautifully with Eclipse. And JUnit 4, which is built into Eclipse 3.2 (in development, but so far quite stable), uses a new JDK 1.5 feature called annotations to make defining test cases even easier.

Now that I’ve tried unit testing, I shall never go back! I’ll definitely add OCUnit tests to LilyPad.