User: sits
Date: 07/07/02 23:29:39
Modified: lib Codestriker.pm
lib/Codestriker/Repository Cvs.pm Subversion.pm
Log:
Using open3() simply doesn't work under mod_perl. Rework some of the external
command calling to only use open3() under CGI, otherwise use regular open()
under mod_perl. We lose error strings using just open(), but at least it
works. Still a work in progress.
Index: Codestriker.pm
===================================================================
RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker.pm,v
retrieving revision 1.98
retrieving revision 1.99
diff -u -r1.98 -r1.99
--- Codestriker.pm 20 Aug 2006 07:11:21 -0000 1.98
+++ Codestriker.pm 3 Jul 2007 06:29:37 -0000 1.99
@@ -13,6 +13,7 @@
use Encode;
use Time::Local;
+use IPC::Open3;
# Export codestriker.conf configuration variables.
use vars qw ( $mailhost $mailuser $mailpasswd $use_compression
@@ -522,5 +523,73 @@
return decode($Codestriker::topic_text_encoding, $string);
}
+# Function for running an external command, and handles the subtle
+# issues for different web servers environments.
+sub execute_command {
+ my $stdout_fh = shift;
+ my $stderr_fh = shift;
+ my $command = shift;
+ my @args = @_;
+
+ # Write error messages to STDERR if the file handle for error messages
+ # is not defined.
+ $stderr_fh = \*STDERR unless defined $stderr_fh;
+
+ if (exists $ENV{'MOD_PERL'}) {
+ # The open3() call simply doesn't work under mod_perl/apache2,
+ # so we need to use open() instead, which is a pain since we lose
+ # error information.
+ my $command_line = "\"$command\"";
+ foreach my $arg (@args) {
+ $command_line .= " \"$arg\"";
+ }
+ my $received_data = 0;
+ if (open(COMMAND, "$command_line |")) {
+ while (<COMMAND>) {
+ print $stdout_fh $_;
+ $received_data = 1;
+ }
+ }
+ if (!$received_data) {
+ print $stderr_fh "Command failed: $!\n";
+ print $stderr_fh "$command_line\n";
+ print $stderr_fh "Check your webserver error log for more
information.\n";
+ }
+ } else {
+ my $write_stdin_fh = new FileHandle;
+ my $read_stdout_fh = new FileHandle;
+ my $read_stderr_fh = new FileHandle;
+
+ # Open3 throws an exception on failure.
+ eval {
+ my $pid = open3($write_stdin_fh, $read_stdout_fh, $read_stderr_fh,
+ $command, @args);
+
+ # Ideally, we should use IO::Select, but that is broken on Win32.
+ # This is not ideal, but read first from stdout. If that is empty,
+ # then an error has occurred, and that can be read from stderr.
+ my $buf = "";
+ while (read($read_stdout_fh, $buf, 16384)) {
+ print $stdout_fh $buf;
+ }
+ while (read($read_stderr_fh, $buf, 16384)) {
+ print $stderr_fh $buf;
+ }
+
+ # Wait for the process to terminate.
+ waitpid($pid, 0);
+ };
+ if ($@) {
+ print $stderr_fh "Command failed: [EMAIL PROTECTED]";
+ print $stderr_fh "$command " . join(' ', @args) . "\n";
+ print $stderr_fh "Check your webserver error log for more
information.\n";
+ }
+ }
+
+ # Flush the output file handles.
+ $stdout_fh->flush;
+ $stderr_fh->flush;
+}
+
1;
Index: Cvs.pm
===================================================================
RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Repository/Cvs.pm,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Cvs.pm 11 Jun 2006 08:40:38 -0000 1.6
+++ Cvs.pm 3 Jul 2007 06:29:38 -0000 1.7
@@ -11,7 +11,6 @@
use strict;
use FileHandle;
-use IPC::Open3;
# Factory method for creating a local CVS repository object.
sub build_local {
@@ -62,17 +61,30 @@
# Open a pipe to the CVS repository.
$ENV{'CVS_RSH'} = $Codestriker::ssh if defined $Codestriker::ssh;
- open(CVS, "\"$Codestriker::cvs\" -q -d \"" . $self->{url} .
- "\" co -p -r $revision \"$filename\" |")
- || die "Can't open connection to pserver CVS repository: $!";
- # Read the data.
- for (my $i = 1; <CVS>; $i++) {
+ my $read_data;
+ my $read_stdout_fh = new FileHandle;
+ open($read_stdout_fh, '>', \$read_data) || die "Can't create in-memory
fh: $!";
+ my @args = ();
+ push @args, '-q';
+ push @args, '-d';
+ push @args, $self->{url};
+ push @args, 'co';
+ push @args, '-p';
+ push @args, '-r';
+ push @args, $revision;
+ push @args, $filename;
+ Codestriker::execute_command($read_stdout_fh, undef,
+ $Codestriker::cvs, @args);
+
+ # Process the data for the topic.
+ open($read_stdout_fh, '<', \$read_data) || die "Can't create in-memory
fh: $!";
+ for (my $i = 1; <$read_stdout_fh>; $i++) {
$_ = Codestriker::decode_topic_text($_);
chop;
$$content_array_ref[$i] = $_;
}
- close CVS;
+ close $read_stdout_fh;
}
# Retrieve the "root" of this repository.
@@ -117,33 +129,12 @@
# Cheat - having two '-u's changes nothing.
my $extra_options = $default_to_head ? '-u' : '-f';
- my $write_stdin_fh = new FileHandle;
- my $read_stdout_fh = new FileHandle;
- my $read_stderr_fh = new FileHandle;
$ENV{'CVS_RSH'} = $Codestriker::ssh if defined $Codestriker::ssh;
- my $pid = open3($write_stdin_fh, $read_stdout_fh, $read_stderr_fh,
- $Codestriker::cvs, '-q', '-d', $self->{url},
- 'rdiff', $extra_options, '-u',
- '-r', $start_tag, '-r', $end_tag, $module_name);
-
- # Ideally, we should use IO::Select, but that is broken on Win32.
- # With CVS, read first from stdout. If that is empty, then an
- # error has occurred, and that can be read from stderr.
- my $buf = "";
- while (read($read_stdout_fh, $buf, 16384)) {
- print $stdout_fh $buf;
- }
- while (read($read_stderr_fh, $buf, 16384)) {
- print $stderr_fh $buf;
- }
-
- # Wait for the process to terminate.
- waitpid($pid, 0);
-
- # Flush the output file handles.
- $stdout_fh->flush;
- $stderr_fh->flush;
+ Codestriker::execute_command($stdout_fh, $stderr_fh, $Codestriker::cvs,
+ '-q', '-d', $self->{url}, 'rdiff',
+ $extra_options, '-u', '-r', $start_tag,
+ '-r', $end_tag, $module_name);
return $Codestriker::OK;
}
Index: Subversion.pm
===================================================================
RCS file:
/cvsroot/codestriker/codestriker/lib/Codestriker/Repository/Subversion.pm,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- Subversion.pm 7 Mar 2007 03:03:40 -0000 1.15
+++ Subversion.pm 3 Jul 2007 06:29:38 -0000 1.16
@@ -48,10 +48,9 @@
# Replace any spaces with %20 uri friendly escapes.
$filename =~ s/ /%20/g;
- my $write_stdin_fh = new FileHandle;
+ my $read_data;
my $read_stdout_fh = new FileHandle;
- my $read_stderr_fh = new FileHandle;
-
+ open($read_stdout_fh, '>', \$read_data) || die "Can't create in-memory
fh: $!";
my @args = ();
push @args, 'cat';
push @args, '--non-interactive';
@@ -60,28 +59,16 @@
push @args, '--revision';
push @args, $revision;
push @args, $self->{repository_url} . '/' . $filename;
-
- my $pid = open3($write_stdin_fh, $read_stdout_fh, $read_stderr_fh,
- $Codestriker::svn, @args);
+ Codestriker::execute_command($read_stdout_fh, undef,
+ $Codestriker::svn, @args);
- # Read the data.
+ # Process the data for the topic.
+ open($read_stdout_fh, '<', \$read_data) || die "Can't create in-memory
fh: $!";
for (my $i = 1; <$read_stdout_fh>; $i++) {
$_ = Codestriker::decode_topic_text($_);
chop;
$$content_array_ref[$i] = $_;
}
-
- # Log anything on standard error to apache error log.
- my $buf;
- my $first_lines = 1;
- while (read($read_stderr_fh, $buf, 16384)) {
- print STDERR "$Codestriker::svn " .
- (join @args, ' ') . "\n" if $first_lines;
- $first_lines = 0;
- print STDERR $buf;
- }
-
- waitpid($pid, 0);
}
# Retrieve the "root" of this repository.
@@ -138,6 +125,11 @@
my $directory;
+ # TODO: need a better way of detecting this, since Chinese users
+ # receive a different output string. svn info might be better,
+ # it can tell you if it is a file or directory.
+ # svn propget svn:mime-type could be a way.
+
# If there is an error about it being a directory, then use the
# module name as a directory.
while(<$read_stderr_fh>) {
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Codestriker-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/codestriker-commits