Friday, October 30, 2009

Vim: Editing ActionScript

It took me an embarrassingly long time to figure out how to install the ActionScript plugin for Vim. First, download it from here. Put it in ~/.vim/syntax. Now, update your ~/.vimrc file to look something like this:
set autoindent
syntax on
filetype plugin on

" Use .as for ActionScript files, not Atlas files.
au BufNewFile,BufRead *.as set filetype=actionscript

" Put these in an autocmd group, so that we can delete them easily.
augroup vimrc
au!
autocmd FileType actionscript setlocal sw=4 sts=4 et
autocmd FileType python setlocal sw=4 sts=4 et tw=72
autocmd FileType ruby setlocal sw=2 sts=2 et
augroup END

Thursday, October 29, 2009

Forking a Subversion Repository Using Git the Brutal Way

I work at a company. We use GitHub. There's a project called CoolProject. CoolProject uses Subversion. I want to fork CoolProject for internal use. There's no use submitting our patches back--they wouldn't want them. I want to maintain our own fork, but I also want to keep updated with changes that they make. Since Subversion isn't a distributed revision control system, forking like this and getting updates is hard. If you know of a better solution than the one I've proposed below, please tell me!

Git has support for Subversion. A great video on how to use it is here. The official documentation for git-svn is here. Here's the gotcha:
For the sake of simplicity and interoperating with a less-capable system (SVN), it is recommended that all git svn users clone, fetch and dcommit directly from the SVN server, and avoid all git clone/pull/merge/push operations between git repositories and branches. The recommended method of exchanging code between git branches and users is git format-patch and git am, or just 'dcommit'ing to the SVN repository.
Having each developer pull and manage their own repository and then share patches manually sounds painful. What I really want is to just check the source code into GitHub and have things just work. I asked on IRC what the best approach was, and I didn't get a response. I searched on the Web, and it seems like everyone using git-svn is working alone--i.e. using Git to work with an existing Subversion repository, but not trying to manage their own running fork with a group of people. I asked vark.com, and me and another guy came up with the following solution.

I checked out all of CoolProject's code from Subversion. I checked it into Git. I created a branch called coolproject_subversion that will be updated with updated with CoolProject's Subversion repository per the method below. My company will commit our changes to master. Once in a while, I'll merge changes from coolproject_subversion to master.

This is a brutally blunt method. We're losing all of Subversion's change history, all their commit messages, etc. However, it lets us keep up to date with their changes, and it lets us keep our own fork--as a group. It's the best thing I could think of. If I need to, I can always look at CoolProject's Subversion repository for log messages, etc.

I think it's a good idea to avoid munging with CoolProject's code as much as possible in order to avoid merge problems. The goal is to keep our code as isolated as possible, and only hack in some integration points. Okay, here's how I got started:
cd somewhere_in_my_git_repo
svn export http://coolproject.googlecode.com/svn/coolproject/trunk/ coolproject
git add *
git commit -a
git checkout -b coolproject_subversion
git checkout master
git push origin HEAD
git push origin coolproject_subversion
Here's how to grab changes from CoolProject's Subversion repository:
git checkout coolproject_subversion
rm -rf * # Double check where you are!
svn export http://coolproject.googlecode.com/svn/coolproject/trunk/ coolproject
git commit -a
git checkout master
git merge coolproject_subversion
git push origin HEAD
git push origin coolproject_subversion
Updated: Use "svn export" instead of using "svn checkout" and then deleting the .svn files.

Saturday, October 17, 2009

Ruby: An Introduction to Behavioral Driven Development with RSpec and Cucumber

On October 20, 2009 at 6:30, I'm going to be giving a talk for the East Bay Ruby Meetup Group called "An Introduction to Behavioral Driven Development with RSpec and Cucumber". This is an introduction to behavioral driven development in Rails using Cucumber, RSpec, Webrat, and factory_girl.

For the second time in my life, I finished preparing several days before the actual talk. If you're interested, here are the slides.

Happy testing! :-D

Thursday, October 15, 2009

Exploding Software-Engineering Myths

If you haven't read Exploding Software-Engineering Myths from Microsoft Research, I highly recommend it.

Tuesday, October 13, 2009

Ruby: Escaping URL Parameters

If you are trying to escape some URL parameters completely separate of Rails' routing infrastructure, URI.escape (AKA URI.encode) is not what you're looking for. In fact, I can't even figure out what problem URI.escape is trying to solve. Consider:
irb(main):003:0> require "uri"
=> true
irb(main):004:0> url = "http://foo.com?a=" + URI.escape("a&b+c")
=> "http://foo.com?a=a&b+c"
What you're looking for is CGI::escape:
irb(main):005:0> require "cgi"
=> true
irb(main):006:0> url = "http://foo.com?a=" + CGI::escape("a&b+c")
=> "http://foo.com?a=a%26b%2Bc"
The same thing goes for URI.decode vs. CGI::unescape.

However, if you're trying parse the query string from a complete URL, try this:
irb(main):008:0> require "uri"
=> false
irb(main):009:0> require "cgi"
=> false
irb(main):010:0> url = "http://foo.com?a=b+c&d=a&d=b"
=> "http://foo.com?a=b+c&d=a&d=b"
irb(main):011:0> uri = URI.parse(url)
=> #<URI::HTTP:0xb7bab258 URL:http://foo.com?a=b+c&d=a&d=b>
irb(main):012:0> uri.query
=> "a=b+c&d=a&d=b"
irb(main):013:0> params = CGI.parse(uri.query)
=> {"a"=>["b c"], "d"=>["a", "b"]}

Friday, October 09, 2009

Ruby: Testing Rake Tasks

I wrote a rake task for my Rails project, and I figured I should write some tests for it. The rake task just creates a certain file, hence it's easy to test. I looked for some entries on testing rake tasks using RSpec.

This blog post shows how to launch rake from within your test--in process. I couldn't get it to work because "Rake" wasn't loaded. This blog post shows how to refactor your rake code into a library that can be more easily tested. I decided to shell out to rake instead.

After reading about the differences between kernel.exec, kernel.system, %x{}, and backticks, I decided to just use backticks. The code ended up being fairly simple since it doesn't require much setup:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe "rake some:task" do
context "subtask" do
it "should create some file containing some stuff" do
begin
`rake some:task:subtask SOME=args`
$?.exitstatus.should == 0
created_file = File.expand_path(File.dirname(__FILE__) + '/../../config/some_subdir/this_got_created.json')
file_contents = File.new(created_file).read()
# Verify the file contents...
ensure
File.unlink(created_file) if File.exist?(created_file)
end
end
end
end
This definitely adds a second or two to my tests, but I'm okay with that.

Saturday, October 03, 2009

Python: How to Blow Up Helicopters Using Pygame

This Thursday, I'm going to be giving a talk for PyGameSF called "How to Blow Up Helicopters Using Pygame". It's a summary of some of the libraries and tricks I used for my two PyWeek entries. I'll be covering topics such as PGU, generator-based animations, and state machine based levels.

For once in my life, I finished preparing several days before the actual talk. If you're interested, here are the slides.

By the way, I used the online service 280 Slides to build my presentation. It was pleasantly simple to use. It felt just a little sluggish compared to desktop software, but for a piece of web-based software, the UI was pretty amazing.