Package: libparse-debianchangelog-perl
Version: 1.2.0-1
Severity: wishlist
Tags: patch

Hi,

I have devised a patch, which makes Parse::DebianChangelog accept open
handles as an input source (instead of just filenames or strings).

A side-effect of this is that parsechangelog no longer needs to slurp
the entire changelog file before starting to parse it.

~Niels
>From df4d8784680fee1c3d593aee32d7a2e782cfabbc Mon Sep 17 00:00:00 2001
From: Niels Thykier <ni...@thykier.net>
Date: Sat, 14 Sep 2013 11:55:01 +0200
Subject: [PATCH] P::DC: Support open handles as input

Signed-off-by: Niels Thykier <ni...@thykier.net>
---
 bin/parsechangelog           |  3 +--
 lib/Parse/DebianChangelog.pm | 31 ++++++++++++++++++++++++-------
 t/Parse-DebianChangelog.t    | 39 +++++++++++++++++++++++++--------------
 3 files changed, 50 insertions(+), 23 deletions(-)

diff --git a/bin/parsechangelog b/bin/parsechangelog
index 7bff43d..3398900 100644
--- a/bin/parsechangelog
+++ b/bin/parsechangelog
@@ -216,8 +216,7 @@ my $changes = Parse::DebianChangelog->init();
 
 $file ||= $default_file;
 if ($file eq '-') {
-    my @input = <STDIN>;
-    $changes->parse({ instring => join('', @input) })
+    $changes->parse({ handle => \*STDIN, handlename => '<stdin>' })
 	or die sprintf( gettext('fatal error occured while parsing %s')."\n",
 			'input' );
 } else {
diff --git a/lib/Parse/DebianChangelog.pm b/lib/Parse/DebianChangelog.pm
index dbb1531..bec10f9 100644
--- a/lib/Parse/DebianChangelog.pm
+++ b/lib/Parse/DebianChangelog.pm
@@ -115,10 +115,10 @@ There are currently no supported general configuration options, but
 see the other methods for more specific configuration options which
 can also specified to C<init>.
 
-If C<infile> or C<instring> are specified (see L<parse>), C<parse()>
-is called from C<init>. If a fatal error is encountered during parsing
-(e.g. the file can't be opened), C<init> will not return a
-valid object but C<undef>!
+If C<infile>, C<instring> or C<handle> are specified (see L<parse>),
+C<parse()> is called from C<init>. If a fatal error is encountered
+during parsing (e.g. the file can't be opened), C<init> will not
+return a valid object but C<undef>!
 
 =cut
 
@@ -134,7 +134,8 @@ sub init {
     $self->init_filters;
     $self->reset_parse_errors;
 
-    if ($self->{config}{infile} || $self->{config}{instring}) {
+    if ($self->{config}{infile} || $self->{config}{instring}
+        || $self->{config}{handle}) {
 	defined($self->parse) or return undef;
     }
 
@@ -250,8 +251,10 @@ sub get_error {
 
 =head3 parse
 
-Parses either the file named in configuration item C<infile> or the string
-saved in configuration item C<instring>.
+Parses either the file named in configuration item C<infile>, the string
+saved in configuration item C<instring> or the open file handle saved
+in the configuration item C<handle>.  In the latter case, the handle can
+be named by using the optional configuration item C<handlename>.
 Accepts a hash ref as optional argument which can contain configuration
 items.
 
@@ -294,6 +297,20 @@ sub parse {
 	}
 	$fh = IO::String->new( $string );
 	$file = 'String';
+    } elsif ($fh = $self->{config}{handle}) {
+        # Scalar::Util is in perlcore, so we can rely on its presence.
+        # (also, if it is broken, then most of perl is as well).
+        require Scalar::Util;
+        if (not Scalar::Util::openhandle($fh)) {
+	    $self->_do_fatal_error( __g('handle is not open'));
+            return undef;
+        }
+
+        $file = $self->{config}{handlename};
+        if (not defined($file)) {
+            $file = '<unnamed-handle>';
+            $file = '<stdin>' if (fileno($fh)//-1) == 0;
+        }
     } else {
 	$self->_do_fatal_error( __g( 'no changelog file specified' ));
 	return undef;
diff --git a/t/Parse-DebianChangelog.t b/t/Parse-DebianChangelog.t
index f3b8270..fe10f6e 100644
--- a/t/Parse-DebianChangelog.t
+++ b/t/Parse-DebianChangelog.t
@@ -17,7 +17,7 @@ BEGIN {
     my $no_err_examples = 1;
     my $no_tests = $no_examples * 13
 	+ $no_err_examples * 2
-	+ 49;
+	+ 51;
 
     require Test::More;
     import Test::More tests => $no_tests, ;
@@ -225,19 +225,30 @@ foreach my $file (qw(Changes t/examples/countme t/examples/shadow)) {
 
 }
 
-open CHANGES, '<', 't/examples/countme';
-my $string = join('',<CHANGES>);
-
-my $str_changes = Parse::DebianChangelog->init( { instring => $string,
-						  quiet => 1 } );
-my $errors = $str_changes->get_parse_errors();
-ok( !$errors,
-    "Parse example changelog t/examples/countme without errors from string" );
-
-my $str_data = $str_changes->rfc822_str({ all => 1 });
-is( $str_data, $save_data,
-    "Compare result of parse from string with result of parse from file" );
-
+for my $i (0..1) {
+    open my $fh, '<', 't/examples/countme' or die "open t/examples/countme: $!";
+    my $str_changes;
+    my $type;
+    if ($i == 0) {
+        my $string = join('', <$fh>);
+
+        $str_changes = Parse::DebianChangelog->init( { instring => $string,
+                                                          quiet => 1 } );
+        $type = 'string';
+    } else {
+        $str_changes = Parse::DebianChangelog->init( { handle => $fh,
+                                                          quiet => 1 } );
+        $type = 'handle';
+    }
+    my $errors = $str_changes->get_parse_errors();
+    ok( !$errors,
+        "Parse example changelog t/examples/countme without errors from $type" );
+
+    my $str_data = $str_changes->rfc822_str({ all => 1 });
+    is( $str_data, $save_data,
+        "Compare result of parse from $type with result of parse from file" );
+    close $fh;
+}
 
 foreach my $test (( [ 't/examples/misplaced-tz', 6 ])) {
 
-- 
1.8.4.rc3

Reply via email to