But it is nowhere near as complex as my process for committing a Rails upgrade to SVN used to be. First I would delete my current Rails version from the repository. Then I would
rake rails:freeze:edge TAG=rel_2-0-2. Finally I would commit the latest Rails version to the repository.
I admit, that doesn’t sound too complex. Problem is this process leads to a completely undeployable revision sitting in SVN. And I’ve also seen very wonky results when looking at
svn status for several minutes after completing such a process. I began to wonder if it wasn’t just coincidence that I sometimes convert the phrase “Subversion repository” into “suppository.” I was feeling it.
rsync, friend to the command-line idiot
Enter rsync, the file copy when
cp just won’t do. If you’ve ever tried to simply overwrite your
vendor/rails directory with a new version, either by using the freeze rake command, a
cp command or a simple drag-and-drop in your GUI, you know how much that can mess with your SVN-chi.
Just. Don’t. Do it.
A simple rsync command will take a source directory (a new version of Rails) and copy all new and updated files to a destination directory (an old version of Rails). It will not copy directories themselves, just files. The expectation when using rsync is that you’re dealing with two similar directory trees.
Here is my current process for upgrading an incremental Rails release. From app root:
cd vendor mv rails rails\_2-0-1 rake rails:freeze:edge TAG=rel_2-0-2 mv rails rails\_2-0-2 cp -rf rails\_2-0-1 rails rsync -arv --delete-after --exclude='.svn/' rails_2-0-2/ rails
And now a blow-by-blow description of this process:
mv rails rails_2-0-1
Move your current version of Rails for safe-keeping.
rake rails:freeze:edge TAG=rel_2-0-2
Freeze your new version of Rails. If you didn’t move
vendor/rails in the previous step, well, now you need to start over. Sorry, buddy.
mv rails rails_2-0-2
Now move your new version of Rails for safe-keeping.
cp -rf rails_2-0-1 rails
Put the original version of Rails back in place. Don’t be your own worst enemy. Use a copy command so you have a recovery path that doesn’t involve recreating the working copy of your app from SVN.
rsync -av --delete-after --exclude='.svn/' rails_2-0-2/ rails
This is the secret sauce of the process. The last two parameters are the source (
rails_2-0-2/) and destination (
rails). The trailing forward-slash on the source parameter is important. If you forget that, rsync will basically copy your
rails_2-0-2 directory into
rails/rails_2-0-2. Not all that useful.
The other options:
-a- archive mode (want recursion and preserve everything)
-v- verbose output
--delete-after- After merging the directory trees, delete from the destination what didn’t exist in the source
--exclude='.svn/'- Don’t even look at
.svndirectories. Without this, all of your SVN hooks will be destroyed
After completing everything, running tests, fixing it all, committing to SVN, etc you can delete those two safe-keeping copies of Rails in your
vendor directory. Now don’t you feel so fresh and so clean?
NOTE: I revert to the first process I describe above with major releases. Jumping from Rails 1.2.* to Rails 2 was jarring enough that there was no real benefit in keeping revision history of such drastic changes. In fact, I’m not entirely sure my new procedure would even work in such a situation.