Well, I originally only set out to build a quick script to help me, then I decided to release it. Now, a few versions later, I find myself without the safety of a suite of behavioural specifications.

I have received three separate reports of piston import being broken. One was even reported in the comments here.

To that end, I have started adding behavioural specifications to Piston. The specs run very slowly, due to the nature of the specifications I wrote:

  1. svnadmin create remote-repository
  2. svn checkout
  3. make some changes
  4. svn commit
  5. svnadmin create local-repository
  6. svn checkout
  7. use the piston commands
  8. working_copy.should match_expectations

Here is one specification:

 1 context "convert with no svn:externals" do
 2   context_setup do
 3     @remote_repos = Repository.new
 4     @rwc = WorkingCopy.new(@remote_repos)
 5     @rwc.checkout
 6     @rwc.mkdir("/trunk")
 8     @rwc.add("/trunk/README", "this is line 1")
 9     @rwc.commit
11     @rwc.add("/trunk/main.c", "int main() { return 0; }")
12     @rwc.commit
14     @local_repos = Repository.new
15     @lwc = WorkingCopy.new(@local_repos)
16     @lwc.checkout
18     @lwc.mkdir("/vendor")
19     @lwc.commit
20     @lwc.update
22     convert(@lwc.path + "/vendor")
23   end
25   setup do
26     convert(@lwc.path + "/vendor")
27   end
29   teardown do
30     @lwc.revert("--recursive")
31     @lwc.status.split.each do |path|
32       FileUtils.rm_rf(path) if path =~ /^\?/
33     end
34   end
36   context_teardown do
37     @lwc.destroy
38     @local_repos.destroy
39     @rwc.destroy
40     @remote_repos.destroy
41   end
43   specify "does not touch the working copy" do
44     @lwc.status.should == ""
45   end
47   def convert(non_options=[], options=[])
48     @command = Piston::Commands::Convert.new([non_options].flatten, options)
49     @command.logging_stream = @stream = StringIO.new
50     @command.run
51   end
52 end

In RSpec documentation, the developers of RSpec say about #context_setup and #context_teardown:

The use of these is generally discouraged, because it introduces dependencies between the specs. Still, it might prove useful for very expensive operations if you know what you are doing.

Well, I did find a use for it. And thank god for that. The specs run in 20 seconds, and I only have three specifications at this time:

 1 $ spec --format=specdoc
 3 import with a valid repository URL
 4 - copies the files into a named directory
 6 convert with no svn:externals
 7 - does not touch the working copy
 9 convert with one svn:externals
10 - removes existing folder to replace with piston export
12 Finished in 18.186754 seconds
14 3 specifications, 0 failures

This journey has been interesting. And interestingly enough, the code I am developing to help me in my specs will help me in the original implementation. I now have real WorkingCopy and Repository objects.

One interesting thing: svnadmin create requires a good entropy source, or else it will block, waiting for more entropy to be generated. I had to recompile Subversion and set --with-devrandom=/dev/urandom. In fact, this is a flag that is passed to APR.

I will release a new Piston version today or tomorrow with at least the golden paths tested.


Your Host

A picture of me

I am François Beausoleil, a Ruby on Rails and Scala developer. During the day, I work on Seevibes, a platform to measure social interactions related to TV shows. At night, I am interested many things. Read my biography.

Top Tags

Books I read and recommend


Projects I work on

Projects I worked on