Guards! Guards!
I'm a big fan of Terry Pratchet. How can you not be a fan of someone who dedicates a book to "the Palace Guard, the City Guard, or the Patrol… Whatever the name, their purpose…is identical: to rush into the room, attack the hero one at a time, and be slaughtered…"
Eclipse and Subversion made me feel like one of those poor guys today. Here's what happened:
1. I checked out a copy of Hippo onto my laptop, and created a directory in which to do the training exercise we've assigned to the incoming students.
2. I fired up Eclipse to create a Java project in that directory. I put my Java source files in a sub-directory called src
, the JAR files my project needed in a sub-directory called lib
, and created an empty directory called bin
for Eclipse to put compiled class files in. I used svn add
to add all three directories to the repository.
3. Reading the Hibernate documentation, I thought I had to put the mapping file that described how to store my Java objects in a database in the same directory as the compiled class files. All right, no problem—I created bin/LoanRecord.hbm.xml
, and used svn add
to add it to the repository.
At this point, my workspace looked like this:
.project # Eclipse project file .classpath # Eclipse classpath file .svn/ # Subversion metadata bin/ .svn/ LoanRecord.hbm.xml # Hibernate metadata lib/ .svn/ hibernate2.jar hsqldb.jar src/ .svn/ LoanRecord.java # my one and only source file
4. I started up Eclipse again, and rebuilt the project, then dropped back to the shell to check the project's status with Subversion:
$ svn status ? bin/LoanRecord.class S bin ! bin/LoanRecord.java
Uh, what? I understand that SVN doesn't know about the class files in the bin
directory, but what's with the "S"? And why does it think that there ought to be a file called bin/LoanRecord.java
?
An hour and a half later, after chatting with Ben Collins-Sussman and others on the Subversion IRC channel, we [1] have an answer. When Eclipse builds your code, it copies the .svn
sub-directory from the src
directory into the output bin
directory. Yup, you heard that right: Eclipse overwrites the .svn
sub-directory in bin
when it compiles [2].
Now, if I could track down Eclipse's developers, they would probably either say, "It's not our fault—Subversion didn't even exist when we started work," or, "Yeah, yeah, we know, our bad, sorry," but I wouldn't accept either. I might forgive them if Eclipse popped up a dialog saying, "Hey, you have some files here that I don't know anything about, do you mind if I crush them?", but it doesn't even do that. Trampling on files and directories that aren't yours is just plain rude; anyone who has been programming for more than a few months ought to know better.
The fix is simple: don't add the bin
directory to the repository [3]. But let's do some math. Assume there are 10,000 Subversion users out there. Assume that a quarter of them are using Eclipse, and that one in ten of those make the same mistake I did (adding the compile output directory to the repository). If each one of them wastes two hours figuring this out (half the time it took us), that's 500 hours, or twelve and a half working weeks. You can write a lot of software in twelve and a half weeks…
Which is what we have to do, now that Eclipse isn't getting in the way. Onward!
[1] David James, Michelle Levesque, and Greg Wilson.
[2] Eclipse doesn't do this to CVS
sub-directories, presumably because its developers use CVS themselves, and fixed the problem the first time it came up. Favoritism, that's what that is…
[3] We tried using Eclipse's inclusin/exclusion filters to prevent it from overwriting the bin/.svn
sub-directory, but couldn't get that to work.