Thursday Apr 26, 2007

Ruby script to toggle CVS root in a workspace

Sandip Chitale posted a Java program that toggles the CVS root setting of a workspace that is already checked out (see A simple program to toggle CVSROOT of existing checked out workspace). At the end of his post, Sandip solicits alternative solutions. I have been playing around with Ruby, and was curious as to how much more compactly the same logic could be expressed in Ruby.

Stripped of empty lines and comments, Sandip's Java solution weighs in at 83 lines. That's roughly four times the 16 lines required for a roughly equivalent program in Ruby, which I give below.

The Java program has explicit exception handlers, which I chose to leave out, since both programs will leave the repository in a corrupted state if IO fails midway.

# A simple program to fix the CVSROOT.  
# 
# One may check out a cvs workspace using a CVSROOT e.g.
# :pserver:username@extranet.foo.com:/cvs. This value of CVSROOT 
# is recorded in the CVS/Root file in the checkedout directories.
# At some later time, depending on the network connectivity, it may be faster
# to use an alternate (aliased) CVSROOT e.g. 
# :pserver:username@intranet.foo.com:/cvs.
#
# This simple program provides the functionality to fix the CVSROOT settings
# in each CVS/Root file. It skips entries found in .cvsignore.
#
# CAUTION: Care must be taken to make sure that both cvs servers are really the
# same servers, or mirrors that are in sync.
#
# DISCLAIMER: This is an experimental program. Use at your own risk.

require 'find'
abort 'No server name specified' unless $\*[0]

roots = []
ignore_patterns = []


# Use the find module to traverse the source code repository, collecting all CVS root
# files found, and patterns of directories to ignore

Find.find('./') do |path|
  if path =~ /CVS\\/Root$/
    roots << path
  elsif path =~ /.cvsignore$/
    ignores = IO.readlines(path).collect{ |line| line.chop }
    ignore_patterns << File.dirname(path) + '/(' + ignores.join('|') + ')'
  end
end


# Construct a regexp of all directories to ignore, use it to prune the array of root
# files, then, update each root file with the new pserver name

ignore_expr = Regexp.new('\^(' + ignore_patterns.join('|') + ')')
roots.reject { |root| ignore_expr.match(root) ? true : false }.each do |root|
  (pserver = File.open(root, 'r').gets)[/@[\^:]+:/] = ('@' + $\*[0] + ':')
  File.open(root, 'w').puts pserver
end 
About

gjmurphy

Search

Top Tags
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today