[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Bug with SVN::Client::diff() and in-memory files

From: Nik Clayton <nik_at_ngo.org.uk>
Date: 2006-11-08 12:57:53 CET

All,

SVN::Client::diff() is supposed to take (as part of its interface) two file
handles, where the output and errors will be sent, respectively.

If these are two file handles that correspond to files on disk then
everything works as expected.

Perl has the facility to open what are called "in memory" files, where the
file corresponds to a Perl variable. This is handy way to avoid having to
create temporary files. However, file handles created in this way don't
work with SVN::Client::diff().

I've attached diff.pl which shows the problem:

Run

   ./diff.pl 0 http://svn.collab.net/repos/svn 2 1

(or use another repo). You should see the diff printed to STDOUT.

Change that to

   ./diff.pl 1 http://svn.collab.net/repos/svn 2 1

to use in-memory files. I get (error message wrapped):

   Bad file descriptor: Can't write to stream: Bad file descriptor at
     diff.pl line 40

This seems to be coming from libsvn_subr/io.c:svn_io_file_write(), which in
turn calls apr_file_write()

As far as Perl is concerned there shouldn't be any difference between the
two types of file handle.

Can anyone else reproduce this?

Some other client functions work correctly. For example, SVN::Client::cat()
works with in memory file handles. Poking through

   subversion/bindings/swig/perl/native/svn_client.c

it looks as though this might be because ::cat()'s first argument is an
svn_stream_t, while ::diff()'s ninth argument is an apr_file_t.

Is there a reason for this discrepency?

N

#!/usr/bin/perl

use strict;
use warnings;

use SVN::Client;
use SVN::Core;
use File::Temp;

# Arguments (all optional):
#
# <in_memory> - true or false, whether to use in-memory files
# <url> - URL for file/directory in a repo
# <rev1> - First rev to diff against
# <rev2> - Second rev to diff against
 
my $in_memory = shift;

my $uri = shift || 'file:///home/nik/.svk/jc/local/CPAN/SVN-Web/trunk';
my $rev1 = shift || 1257;
my $rev2 = shift || 1250;
my $ctx = SVN::Client->new();

my($out_fh, $err_fh, # File handles
   $out, $err, # Vars for in-memory open()
   $out_fn, $err_fn); # Filenames

if($in_memory) {
    # This should work, but produces the error:
    #
    # Bad file descriptor: Can't write to stream: Bad file descriptor
    #
    # in the call to diff().
    open($out_fh, '>', \$out) or die;
    open($err_fh, '>', \$err) or die;
} else {
    ($out_fh, $out_fn) = File::Temp::tempfile();
    ($err_fh, $err_fn) = File::Temp::tempfile();
}

$ctx->diff([], $uri, $rev1, $uri, $rev2, 0, 1, 0, $out_fh, $err_fh);

local $/ = undef;
seek($out_fh, 0, 0);
print <$out_fh>;

close($out_fh);
close($err_fh);

if(! $in_memory) { # Delete temp files if necessary
    unlink($out_fn);
    unlink($err_fn);
}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Nov 8 12:58:20 2006

This is an archived mail posted to the Subversion Dev mailing list.