I did something unusual today. I pulled the plug on one of my own projects.

In Solving the CVS-lifting problem and Announcing cvs-fast-export I described how I accidentally ended up maintaining two different CVS-to-something-else exporters.

I finally got enough round tuits to put together two-thirds of the head-to-head comparison I’ve been meaning to do – that is, compare the import-stream output of cvs-fast-export to that of cvsps to see how they rate against each other. I wrote both git-stream output stages, so this was really a comparison of the analysis engines.

I wasn’t surprised which program did a better job; I’ve read and modified both pieces of code, after all. Keith Packard’s analysis engine, in cvs-fast-export, is noticeably more elegant and craftsmanlike than the equivalent in cvsps. (Well, duh. Yeah, that Keith Packard, the co-architect of X.)

What did surprise me was the magnitude of the quality difference once I could actually compare them head-to-head. Bletch. Turns out it’s not a case of a good job versus mildly flaky, but of good job versus suckage.

The comparison, and what I discovered when I tried to patch cvsps to behave less badly, was so damning that I did something I don’t remember ever having felt the need to do before. I shot one of my own projects through the head.

The wrong thing to do in this situation is to just let the bad code hang out there in the noosphere gradually bitrotting, with no maintainence and warnings to people who might stumble over it and think it’s safe to use or salvageable. This is bad for the same reasons abandoning a physical building and letting it decay into a public hazard is bad,

Instead, I shipped a final archival release with an end-of-life notice, prominent warnings in the documentations about the Bad Things that are likely to happen if you try to use it, and a pointer to a better alternative.

This is the right thing to do. The responsible thing. Which I’m making a point of since I’ve too often seen people fall into doing the wrong thing – usually through embarrassment at the prospect of admitting that they made a mistake or, possibly, can’t meet the qualifications to finish what they started.

I’ll say it straight up: I tried hard, but I can’t fix cvsps. Peeling away the shims and kluges and junk just reveals more shims and kluges and junk. Well, in the repo-analysis code, anyway; there’s another piece, a partial CVS client for fetching metadata out of remote CVS repositories, that is rather good. It’s why I kept trying to salvage the whole mess for about ten months longer than I should have.

What I think happened here is that the original author of cvsps did a fast, sloppy ad-hoc job that worked well enough for simple cases but never matured because he didn’t encounter the less simple ones. Keith, on the other hand, did what I would do in like circumstances – thought the problem entirely through on an algorithmic level and nuked it flat. His code is solid.

One of the differences that makes is that Keith’s code copes better when put under unanticipated stress, such as me coming along and sawing off the entire git-aware output back end to replace it with a stream-file emitter. But I digress. I’m not here today to talk about architecture, but about how to demolish your project with style.

Software is communication to other human beings as much, or more so, than it is communication to computers. As an open-source hacker, you are part of a craft community with a past and a future. If you care about your craft and your community, the end of a project leaves you with a duty to clean up after it so that it becomes a positive lesson to those who come after you, rather than a trap and attractive nuisance.

And now I’ll get off my soapbox and go back to work. On cvs-fast-export. After this, making sure it has a really good test suite before I ship 1.0 seems even more important.