package VCfs::Setup; use strict; use warnings; use File::chdir; use File::Path; use File::Temp qw(tempdir); use Test::More; use base 'Exporter'; our @EXPORT = qw(working_vcs_types setup); =head1 NAME VCfs::Setup - Setup repositories for testing =head1 SYNOPSIS use Test::More; use VCfs::Setup; for my $type (working_vcs_types()) { my $checkout_dir = setup( type => $vcs ); new_ok VCfs => [$checkout_dir]; ...your tests... } =head1 DESCRIPTION This is a module to setup repositories and checkout projects for testing. It smooths this process out so we can use the same tests for all repository types. This should probably go into VCfs itself, but I'm just testing what's there right now. =head2 working_vcs_types my @types = working_vcs_types(); Returns all the version control systems which we can test in this environment. =cut my $checks = { svn => sub { # Check we have svnadmin and svn return 0 unless `svnadmin --version` && $? == 0; return 0 unless `svn --version` && $? == 0; return 1; }, svk => sub { my $version_line = `svk --version`; return 0 unless $? == 0; my($version) = $version_line =~ m{version v([\d.]+)}; return 0 unless $version; $version = version->new($version); # SVK before 2.2.0 doesn't have SVKBATCHMODE so it will hang around # waiting for a human return 0 unless $version ge v2.2.0; return 1; }, git => sub { return 0 unless `git --version` && $? == 0; return 1; }, }; sub working_vcs_types { my @types; for my $type ( VCfs->_vcs_types ) { push @types, $type if $checks->{$type}->(); } return @types; } =head2 setup my $checkout_dir = setup( type => $vcs_type ); Will set up a repository and check out revision 0. Both will be automatically cleaned up when the test exits. =cut my %setup_for = ( svn => sub { my $tmpdir = tempdir( CLEANUP => 1 ); my $repo_dir = "$tmpdir/repo"; my $repo_url = "file://$repo_dir"; my $co_dir = "$tmpdir/checkout"; note("Creating SVN repo at $repo_dir"); note `svnadmin create $repo_dir`; die "svnadmin create failed" if $?; note `svn co $repo_url $co_dir`; die "svn co $repo_url failed" if $? or !-d $co_dir; return $co_dir; }, svk => sub { my $tmpdir = tempdir( CLEANUP => 1 ); my $repo_dir = "$tmpdir/repo"; my $co_dir = "$tmpdir/checkout"; $ENV{SVKROOT} = "$tmpdir/svkroot"; $ENV{SVKBATCHMODE} = 1; note `svk depotmap -i`; die "svk init failed" if $?; note `svk co // $co_dir`; die "svk co // $co_dir failed" if $? or !-d $co_dir; return $co_dir; }, git => sub { my $tmpdir = tempdir( CLEANUP => 1 ); my $co_dir = "$tmpdir/checkout"; mkdir $co_dir or die $!; local $CWD = $co_dir; note `git init`; die "git init failed" if $?; # Git needs at least one commit to do some things. open my $fh, ">", ".gitignore"; close $fh; `git add .gitignore`; `git commit -m 'Something to get the repo off the ground'`; return $co_dir; }, ); sub setup { my %args = @_; return $setup_for{$args{type}}->(); } "poop is good food";