Custom Subversion Rake Task, Part 2

In this long overdue follow up to Custom Subversion Rake Tasks, Part I, I will guide you through the remainder of my custom Subversion Rake Tasks (svn:add,svn:delete, svn:update, svn:commit, and svn:status).

rake snv:add

task :add do
  files = `svn status`.split("\n").find_all{ |f| f =~ /^\?/ }.collect { |f| f.split()[1] }
  puts `svn add #{files.join(" ")} --force` unless files.empty?
end

Add new files (svn status of ‘?’) to the Subversion repository. We perform an svn status call, split the response string into an array and search the array for any line that starts with a ‘?’. For each line that we find, we split the string to store only the filename. To perform the svn add in one line, we join all of our filenames with a space.

rake svn:commit

task :commit => [:add, :delete, :update] do
  comment = ENV['comment'] || ENV['m']
  comment = '[rake svn:commit with no comment]' if not comment or '' == comment
  puts `svn commit -m '#{comment}'`
end

Commit files to the Subversion repository. To add comments to our commit we use rake svn:commit m="message" or more detailed, rake svn:commit comment="message". This task will perform svn:add and svn:delete to get a complete commit, and svn:update to get the latest code, check for conflicts, and run our rake tests to ensure a clean commit.

rake svn:delete

task :delete do
  files = `svn status`.split("\n").find_all{ |f| f =~ /^\!/ }.collect { |f| f.split()[1] }
  puts `svn delete #{files.join(" ")} --force` unless files.empty?
end

Remove deleted files (svn status of ‘!’) from the Subversion repository. Implementation is the same as svn:add above.

rake svn:status

task :status do
  files = `svn status`.split("\n")
  
  modified = files.grep /^M/
  puts "", "Changed Files", "-------------------------", modified unless modified.empty?
  files = files - modified
  
  added = files.grep /^(A|\?)/
  puts "", "Files to Add", "-------------------------", added unless added.empty?
  files = files - added
  
  deleted = files.grep /^(D|!)/
  puts "", "Files to Delete", "-------------------------", deleted unless deleted.empty?
  files = files - deleted
  
  puts "", "UNKNOWN ACTION", "-------------------------", files unless files.empty?
  puts ""
end

Show the status of your local files as compared to the Subversion repository, grouped by Modified, Added, Deleted, and Unknown. An example of ‘unknown’ is svn externals (svn status ‘X’), where we just let svn do it’s thing.

rake svn:updat

task :update do
  files = `svn up`
  puts files
  raise "One or more conflicts found." unless files.grep(/^C/).empty?
  Rake::Task["db:migrate"].invoke
  Rake::Task[:test].invoke
end

Update files from the Subversion repository, raises an error if conflicts (svn status ‘C’) were found that could not be merged (svn status ‘G’). If the svn up goes well, we rake the database if needed and run our test suite to ensure everything is kosher.

Wheh! That wasn’t so bad, I don’t know why it took me over a month to get this out. Well, I’m off to RailsConf 2008 tomorrow. Going to try to take in some of the city (Portand, Oregon) tomorrow night, before all of the Rails madness starts in with the Tutorial Sessions on Thursday :)