From aafd267ee099ddb8ff4129a0e4d46964be866f6d Mon Sep 17 00:00:00 2001 From: Amitai Schlair Date: Wed, 9 Sep 2009 21:58:42 -0400 Subject: [PATCH 1/3] Abstract out CVS's involvement in the wrapper: * In Wrapper.pm, add a new hook "wrapperargcheck" to examine argc/argv and return success or failure. In the failure case, the wrapper terminates. * In cvs.pm, implement the new hook to return failure if a directory is being cvs added. --- IkiWiki/Plugin/cvs.pm | 12 ++++++++++++ IkiWiki/Wrapper.pm | 21 +++++++++------------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/IkiWiki/Plugin/cvs.pm b/IkiWiki/Plugin/cvs.pm index 8409bebed..ff9d578e2 100644 --- a/IkiWiki/Plugin/cvs.pm +++ b/IkiWiki/Plugin/cvs.pm @@ -6,6 +6,7 @@ use strict; use IkiWiki; sub import { + hook(type => "wrapperargcheck", id => "cvs", call => \&wrapperargcheck); hook(type => "checkconfig", id => "cvs", call => \&checkconfig); hook(type => "getsetup", id => "cvs", call => \&getsetup); hook(type => "rcs", id => "rcs_update", call => \&rcs_update); @@ -20,6 +21,17 @@ sub import { hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime); } +sub wrapperargcheck () { + my $check_args=<<"EOF"; + int j; + for (j = 1; j < argc; j++) + if (strstr(argv[j], "New directory") != NULL) + return 0; + return 1; +EOF + return $check_args; +} + sub checkconfig () { if (! defined $config{cvspath}) { $config{cvspath}="ikiwiki"; diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm index cc2223d7a..0baf112ff 100644 --- a/IkiWiki/Wrapper.pm +++ b/IkiWiki/Wrapper.pm @@ -44,17 +44,8 @@ EOF $test_receive=IkiWiki::Receive::gen_wrapper(); } - my $check_cvs_add_dir=""; - if ($config{rcs} eq 'cvs') { - $check_cvs_add_dir=<<"EOF"; - { - int j; - for (j = 1; j < argc; j++) - if (strstr(argv[j], "New directory") != NULL) - exit(0); - } -EOF - } + my $check_args=" return 0;"; + run_hooks(wrapperargcheck => sub { $check_args = shift->(); }); my $check_commit_hook=""; my $pre_exec=""; @@ -128,10 +119,16 @@ addenv(char *var, char *val) { newenviron[i++]=s; } +int checkargs(int argc, char **argv) { +$check_args +} + int main (int argc, char **argv) { char *s; -$check_cvs_add_dir + if (!checkargs(argc, argv)) + exit(0); + $check_commit_hook $test_receive $envsave From 12bbc6c919ca5333a69715e5909263c4e9e4e514 Mon Sep 17 00:00:00 2001 From: Amitai Schlair Date: Wed, 9 Sep 2009 23:09:26 -0400 Subject: [PATCH 2/3] Add automated tests, modeled after svn's. Note the chdir() calls; perhaps cvs.pm should be doing pushd/popd in case the caller expects its working directory to be left alone. --- t/cvs.t | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 t/cvs.t diff --git a/t/cvs.t b/t/cvs.t new file mode 100755 index 000000000..c3612ef8c --- /dev/null +++ b/t/cvs.t @@ -0,0 +1,76 @@ +#!/usr/bin/perl +use warnings; +use strict; +my $dir; +BEGIN { + $dir="/tmp/ikiwiki-test-cvs.$$"; + my $cvs=`which cvs`; + chomp $cvs; + if (! -x $cvs || ! mkdir($dir)) { + eval q{ + use Test::More skip_all => "cvs not available or could not make test dir" + } + } +} +use Test::More tests => 12; + +BEGIN { use_ok("IkiWiki"); } + +%config=IkiWiki::defaultconfig(); +$config{rcs} = "cvs"; +$config{srcdir} = "$dir/src"; +$config{cvsrepo} = "$dir/repo"; +$config{cvspath} = "ikiwiki"; +IkiWiki::loadplugins(); +IkiWiki::checkconfig(); + +my $cvsrepo = "$dir/repo"; + +system "cvs -d $cvsrepo init >/dev/null"; +system "mkdir $dir/ikiwiki >/dev/null"; +my $cwd = `pwd`; chomp $cwd; +system "cd $dir/ikiwiki && cvs -d $cvsrepo import -m import ikiwiki VENDOR RELEASE >/dev/null"; +chdir $cwd; +system "rm -rf $dir/ikiwiki >/dev/null"; +system "cvs -d $cvsrepo co -d $config{srcdir} ikiwiki >/dev/null"; + +# Web commit +chdir $cwd; +my $test1 = readfile("t/test1.mdwn"); +writefile('test1.mdwn', $config{srcdir}, $test1); +IkiWiki::rcs_add("test1.mdwn"); +IkiWiki::rcs_commit("test1.mdwn", "Added the first page", "moo"); + +my @changes; +@changes = IkiWiki::rcs_recentchanges(3); + +is($#changes, 0); +is($changes[0]{message}[0]{"line"}, "Added the first page"); +is($changes[0]{pages}[0]{"page"}, "test1"); + +# Manual commit +my $message = "Added the second page"; + +chdir $cwd; +my $test2 = readfile("t/test2.mdwn"); +writefile('test2.mdwn', $config{srcdir}, $test2); +chdir $config{srcdir}; +system "cvs add test2.mdwn >/dev/null 2>&1"; +system "cvs commit -m \"$message\" test2.mdwn >/dev/null"; + +@changes = IkiWiki::rcs_recentchanges(3); +is($#changes, 1); +is($changes[0]{message}[0]{"line"}, $message); +is($changes[0]{pages}[0]{"page"}, "test2"); +is($changes[1]{pages}[0]{"page"}, "test1"); + +# extra slashes in the path shouldn't break things +$config{cvspath} = "/ikiwiki//"; +IkiWiki::checkconfig(); +@changes = IkiWiki::rcs_recentchanges(3); +is($#changes, 1); +is($changes[0]{message}[0]{"line"}, $message); +is($changes[0]{pages}[0]{"page"}, "test2"); +is($changes[1]{pages}[0]{"page"}, "test1"); + +system "rm -rf $dir"; From 98553d15375a373bd769b82cea24b48ee9613662 Mon Sep 17 00:00:00 2001 From: Amitai Schlair Date: Thu, 10 Sep 2009 00:51:34 -0400 Subject: [PATCH 3/3] CVS operations generally need to be within CVS checkouts, so these chdir() calls are warranted. They shouldn't modify the caller's working directory, though. Use File::chdir to keep the scope of the changes subroutine-local. The tests now pass without resetting the working directory. --- IkiWiki/Plugin/cvs.pm | 12 +++++++----- t/cvs.t | 9 ++------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/IkiWiki/Plugin/cvs.pm b/IkiWiki/Plugin/cvs.pm index ff9d578e2..e926425f2 100644 --- a/IkiWiki/Plugin/cvs.pm +++ b/IkiWiki/Plugin/cvs.pm @@ -5,6 +5,8 @@ use warnings; use strict; use IkiWiki; +use File::chdir; + sub import { hook(type => "wrapperargcheck", id => "cvs", call => \&wrapperargcheck); hook(type => "checkconfig", id => "cvs", call => \&checkconfig); @@ -104,7 +106,7 @@ sub cvs_info ($$) { my $field=shift; my $file=shift; - chdir $config{srcdir} || error("Cannot chdir to $config{srcdir}: $!"); + local $CWD = $config{srcdir}; my $info=`cvs status $file`; my ($ret)=$info=~/^\s*$field:\s*(\S+)/m; @@ -115,7 +117,7 @@ sub cvs_runcvs(@) { my @cmd = @_; unshift @cmd, 'cvs', '-Q'; - chdir $config{srcdir} || error("Cannot chdir to $config{srcdir}: $!"); + local $CWD = $config{srcdir}; open(my $savedout, ">&STDOUT"); open(STDOUT, ">", "/dev/null"); @@ -261,7 +263,7 @@ sub rcs_rename ($$) { return unless cvs_is_controlling; - chdir $config{srcdir} || error("Cannot chdir to $config{srcdir}: $!"); + local $CWD = $config{srcdir}; if (system("mv", "$src", "$dest") != 0) { warn("filesystem rename failed\n"); @@ -280,7 +282,7 @@ sub rcs_recentchanges($) { eval q{use Date::Parse}; error($@) if $@; - chdir $config{srcdir} || error("Cannot chdir to $config{srcdir}: $!"); + local $CWD = $config{srcdir}; # There's no cvsps option to get the last N changesets. # Write full output to a temp file and read backwards. @@ -400,7 +402,7 @@ sub rcs_recentchanges($) { sub rcs_diff ($) { my $rev=IkiWiki::possibly_foolish_untaint(int(shift)); - chdir $config{srcdir} || error("Cannot chdir to $config{srcdir}: $!"); + local $CWD = $config{srcdir}; # diff output is unavoidably preceded by the cvsps PatchSet entry my @cvsps = `env TZ=UTC cvsps -q --cvs-direct -z 30 -g -s $rev`; diff --git a/t/cvs.t b/t/cvs.t index c3612ef8c..9df62334d 100755 --- a/t/cvs.t +++ b/t/cvs.t @@ -28,14 +28,11 @@ my $cvsrepo = "$dir/repo"; system "cvs -d $cvsrepo init >/dev/null"; system "mkdir $dir/ikiwiki >/dev/null"; -my $cwd = `pwd`; chomp $cwd; system "cd $dir/ikiwiki && cvs -d $cvsrepo import -m import ikiwiki VENDOR RELEASE >/dev/null"; -chdir $cwd; system "rm -rf $dir/ikiwiki >/dev/null"; system "cvs -d $cvsrepo co -d $config{srcdir} ikiwiki >/dev/null"; # Web commit -chdir $cwd; my $test1 = readfile("t/test1.mdwn"); writefile('test1.mdwn', $config{srcdir}, $test1); IkiWiki::rcs_add("test1.mdwn"); @@ -51,12 +48,10 @@ is($changes[0]{pages}[0]{"page"}, "test1"); # Manual commit my $message = "Added the second page"; -chdir $cwd; my $test2 = readfile("t/test2.mdwn"); writefile('test2.mdwn', $config{srcdir}, $test2); -chdir $config{srcdir}; -system "cvs add test2.mdwn >/dev/null 2>&1"; -system "cvs commit -m \"$message\" test2.mdwn >/dev/null"; +system "cd $config{srcdir} && cvs add test2.mdwn >/dev/null 2>&1"; +system "cd $config{srcdir} && cvs commit -m \"$message\" test2.mdwn >/dev/null"; @changes = IkiWiki::rcs_recentchanges(3); is($#changes, 1);