#! /usr/bin/perl -w sub usage() { print STDERR "extract-hunks regex patch.diff [out_with.diff [out_without.diff]] Extract hunks from diff based on regex. regex Regular expression for matching patch.diff Patch that will be separated out_with.diff Output patch that will contain the hunks matching regex out_without.diff Output patch with non-mathing hunks\n"; exit 1; } $regex = shift; $patch = shift; $out_with = shift; $out_without = shift; usage() if ( ! defined( $regex ) || ! defined( $patch ) ); $out_with = "with-" . $patch if ( ! defined( $out_with ) ); $out_without = "without-" . $patch if ( ! defined( $out_without ) ); usage() if ( $out_with eq $patch || $out_without eq $patch ); # open the files my $PATCH; my $WITH; my $WITHOUT; if ( ! open( $PATCH, "$patch" ) ) { print STDERR "Unable to open patch '$patch'."; exit 1; } if ( ! open( $WITH, ">$out_with" ) ) { print STDERR "Unable to open '$out_with'."; exit 1; } if ( ! open( $WITHOUT, ">$out_without" ) ) { print STDERR "Unable to open '$out_without'."; exit 1; } # do the job my $hunk = ""; my $header_with = ""; my $header_without = ""; my $regex_found = 0; my $reset_header = 0; my $plus_lines = 0; my $minus_lines = 0; my $line; my $lineno = 0; while ( $line = <$PATCH>) { ++$lineno; # beginning of a hunk if ( $line =~ /^@@ [^,]*,([^ ]*) [^,]*,([^ ]*)/ ) { $hunk = $line; $minus_lines = $1; $plus_lines = $2; $regex_found = 0; next; } # inside a hunk if ( $plus_lines > 0 || $minus_lines > 0 ) { $hunk .= $line; if ( $line =~ $regex ) { $regex_found = 1; } if ( $line =~ /[^ \+\-]/ ) { --$plus_lines if ( $line =~ /^[ \+]/ ); --$minus_lines if ( $line =~ /^[ \-]/ ); } else { print STDERR "Cannot handle line $lineno: $line\n"; close( $PATCH ); close( $WITH ); close( $WITHOUT ); exit 1; } # end of the hunk if ( $plus_lines == 0 && $minus_lines == 0 ) { if ( $regex_found ) { print $WITH $header_with . $hunk; $header_with = ""; } else { print $WITHOUT $header_without . $hunk; $header_without = ""; } $reset_header = 1; } } # inside a header else { if ( $reset_header ) { $header_with = ""; $header_without = ""; $reset_header = 0; } $header_with .= $line; $header_without .= $line; } } close( $PATCH ); close( $WITH ); close( $WITHOUT );