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

Re: checkout to stdout (cvs -p)?

From: David M. Jones <dmj_at_ams.org>
Date: 2006-05-18 20:17:54 CEST

package StringHandle;

use strict;
use warnings;

use Carp;

## NOTE: This is basically just a proof-of-concept. It implements
## just enough to allow a StringHandle to be used as the filehandle
## argument to SVN::Client::cat without getting bogged down in
## annoying questions of robustness. Use at your own risk.

## WARNING: Although as currently implemented, this code seems to
## allow or even encourage mixed WRITES and reads, don't do that (see
## the comments in the implementation of READLINE).

## The comments prefixed with "#*" are quoted from the perltie
## manpage, which should be consulted for the details.

#*TIEHANDLE classname, LIST
#* This is the constructor for the class. That means it is expected
#* to return a blessed reference of some sort. The reference can be
#* used to hold some internal information.

sub TIEHANDLE {
    my $class = shift;

    my $self = {
        lines => [],
        buffer => undef,
    };

    return bless $self, $class;
}

#*WRITE this, LIST
#* This method will be called when the handle is written to via the
#* "syswrite" function.

sub WRITE {
    my $self = shift;

    my $buf = shift;
    my $len = shift;
    my $off = shift || 0;

    my $data = substr($buf, $off, $len);

    $self->{buffer} .= $data;

    return length $data;
}

#*PRINT this, LIST
#* This method will be triggered every time the tied handle is
#* printed to with the "print()" function. Beyond its self reference
#* it also expects the list that was passed to the print function.

sub PRINT {
    my $self = shift;

    my $data = join($,, @_) . $\;

    $self->{buffer} .= $data;

    return 1;
}

#*PRINTF this, LIST
#* This method will be triggered every time the tied handle is
#* printed to with the "printf()" function. Beyond its self refer-
#* ence it also expects the format and list that was passed to the
#* printf function.

sub PRINTF {
    my $self = shift;

    my $fmt = shift;

    my $data = sprintf($fmt, @_);

    $self->{buffer} .= $data;

    return 1;
}

#*READ this, LIST
#* This method will be called when the handle is read from via the
#* "read" or "sysread" functions.

sub READ {
    my $self = shift;

    croak "READ not implemented";
}

#*READLINE this
#* This method will be called when the handle is read from via <HAN-
#* DLE>. The method should return undef when there is no more data.

sub READLINE {
    my $self = shift;

    if (defined $self->{buffer}) {

        ## BUG: If the buffer doesn't end in a record separator, this
        ## will result in a line getting broken in two. But as long
        ## as you write all data to the filehandle before trying to
        ## read, you should be ok.

        push @{ $self->{lines} }, split $/, $self->{buffer};
        $self->{buffer} = undef;
    }

    return wantarray ? @{ $self->{lines} } : shift @{ $self->{lines} };
}

#*GETC this
#* This method will be called when the "getc" function is called.

sub GETC {
    croak "GETC not implemented";
}

#*CLOSE this
#* This method will be called when the handle is closed via the
#* "close" function.

sub CLOSE {
    return 1;
}

#*UNTIE this
#* As with the other types of ties, this method will be called when
#* "untie" happens. It may be appropriate to "auto CLOSE" when this
#* occurs. See "The "untie" Gotcha" below.

#*DESTROY this
#* As with the other types of ties, this method will be called when
#* the tied handle is about to be destroyed. This is useful for
#* debugging and possibly cleaning up.

sub DESTROY {
    my $self = shift;
}

1;

__END__

> Mailing-List: contact users-help@subversion.tigris.org; run by ezmlm
> Date: Thu, 18 May 2006 15:12:55 +0300
> From: Saku Ytti <saku+svn@ytti.fi>
> Content-Disposition: inline
>
> On (2006-05-18 13:47 +0200), Anders J. Munch wrote:
>
> > So what's a FILEHANDLE in perl? Can it be some sort of virtual file
> > that when written to builds up a string (like stringstream in C++ or
> > StringIO in python)? If it absolutely has to be an integer that
> > refers to some OS-level resource, you could perhaps create a pipe for
> > that, using a second thread to read from the pipe.
>
> I asked this from some of our perl guys, they couldn't immediately
> think of a way how to get that FILEHANDLE to an array instead.

Perl filehandles are just barely object-oriented enough to allow this
to be done via the tie mechanism (see the perltie manpage). I
expected there to be something like this on CPAN, but a quick search
didn't turn anything up. So, I've attached a very simple class that
allows something like this to work:

    #!/usr/bin/perl -w
    
    use strict;
    use warnings;
    
    use StringHandle;
    
    use SVN::Client;
    
    my $SVN = SVN::Client->new();
    
    tie(*FH, 'StringHandle');
    
    my $target = 'http://svn.collab.net/repos/svn/trunk/README';
    
    $SVN->cat(\*FH, $target, 'HEAD');
    
    ## This works:
    
    my @lines = <FH>;
    
    for my $line (@lines) {
        print $line, "\n";
    }
    
    ## and so does this:
    
    ## while (my $line = <FH>) {
    ## print $line, "\n";
    ## }
    
    __END__

I doubt this will solve the entire problem for you, but hopefully it
will give you some ideas of how to proceed.

Cheers,
David.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Thu May 18 20:19:43 2006

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.