|
Chris L Mason |
e00945 |
#!/usr/bin/perl
|
|
Michal Marek |
0a417c |
#############################################################################
|
|
Michal Marek |
0a417c |
# Copyright (c) 2004,2005 Novell, Inc.
|
|
Michal Marek |
0a417c |
# All Rights Reserved.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# This program is free software; you can redistribute it and/or
|
|
Michal Marek |
0a417c |
# modify it under the terms of version 2 of the GNU General Public License as
|
|
Michal Marek |
0a417c |
# published by the Free Software Foundation.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# This program is distributed in the hope that it will be useful,
|
|
Michal Marek |
0a417c |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Michal Marek |
0a417c |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Michal Marek |
0a417c |
# GNU General Public License for more details.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# You should have received a copy of the GNU General Public License
|
|
Michal Marek |
0a417c |
# along with this program; if not, contact Novell, Inc.
|
|
Michal Marek |
0a417c |
#
|
|
Michal Marek |
0a417c |
# To contact Novell about this file by physical or electronic mail,
|
|
Michal Marek |
0a417c |
# you may find current contact information at www.novell.com
|
|
Michal Marek |
0a417c |
#############################################################################
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag is meant to maintain a set of metadata tags in a diff. Multiple
|
|
Chris L Mason |
e00945 |
# files can be specified on the command line and all options can be
|
|
Chris L Mason |
e00945 |
# given more than once.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# All options can be abbreviated. --print is the same as -p
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# All tags are changed so the first letter is uppercase and the rest are
|
|
Chris L Mason |
e00945 |
# lowercase.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# Example usage:
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag file
|
|
Chris L Mason |
e00945 |
# print the entire header before the diff starts
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -e filename
|
|
Chris L Mason |
e00945 |
# Runs $EDITOR on filename. If there are no tags in the file yet
|
|
Chris L Mason |
e00945 |
# a default set of tags is filled in. See $default_comment for the
|
|
Chris L Mason |
e00945 |
# list.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -p Author -p Subject file
|
|
Chris L Mason |
e00945 |
# print the author and subject tags only
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
118480 |
# patch-tag -s [-p tag] file
|
|
Chris L Mason |
118480 |
# prints in summary form, default tags are Subject and References
|
|
Chris L Mason |
118480 |
#
|
|
Chris L Mason |
e00945 |
# --print forces everything into readonly mode. If you specify --tag
|
|
Chris L Mason |
e00945 |
# along with --print, the file won't be changed although the output on stdout
|
|
Chris L Mason |
e00945 |
# will.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e2d213 |
# patch-tag -P file
|
|
Chris L Mason |
e2d213 |
# Prints only the comments other then tags in the file.
|
|
Chris L Mason |
e2d213 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -t author=Mason -t subject="a patch to fix an oops"
|
|
Chris L Mason |
e00945 |
# Add or modify the author and subject tags. If more than one
|
|
Chris L Mason |
e00945 |
# author tag is already present in the comment, only the first will
|
|
Chris L Mason |
e00945 |
# be changed.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -a author -a Subject=patch
|
|
Chris L Mason |
e00945 |
# Add an empty author tag and Subject: patch tag to the patch,
|
|
Chris L Mason |
e00945 |
# but don't overwrite any existing values if these tags were present
|
|
Chris L Mason |
e00945 |
# already.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -a filename
|
|
Chris L Mason |
e00945 |
# Read in a list of tags for -a from filename
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -A works the same as -a, but always adds the new tag, even
|
|
Chris L Mason |
e00945 |
# if one is already present.
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# patch-tag -c filename
|
|
Chris L Mason |
e00945 |
# Read a whole new comment block from stdin for filename.
|
|
Chris L Mason |
c34d28 |
# patch-tag -C string filename
|
|
Chris L Mason |
c34d28 |
# Replace the non-tag comment with string if it does not exist
|
|
Chris L Mason |
ba7397 |
# patch-tag -m filename
|
|
Chris L Mason |
ba7397 |
# Concatenate multiline tags into one line
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
# The template files for -a can have comments starting with #. Only lines
|
|
Chris L Mason |
e00945 |
# starting with string: will be used as tags. The tags may have default
|
|
Chris L Mason |
ba7397 |
# values. You can also place the template file into ~/.patchtag, it will
|
|
Chris L Mason |
ba7397 |
# be used automatically
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
use strict;
|
|
Chris L Mason |
e00945 |
use Getopt::Long qw(:config no_ignore_case);
|
|
Chris L Mason |
e00945 |
use File::Temp;
|
|
Chris L Mason |
e00945 |
use IO::File;
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
c34d28 |
my $VERSION = "0.11";
|
|
Chris L Mason |
e00945 |
|
|
Jean Delvare |
c99488 |
my $default_comment = "from:subject:patch-mainline:Git-commit:references:signed-off-by:acked-by:reviewed-by:";
|
|
Jean Delvare |
c99488 |
my $post_comment_tags = "signed-off-by acked-by reviewed-by";
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
c5851a |
# when these are in the bk comment, and non-bk section, use the non-bk one
|
|
Chris L Mason |
c5851a |
my $non_dup_tags = "from subject";
|
|
Chris L Mason |
c5851a |
|
|
Chris L Mason |
e00945 |
# command line options
|
|
Chris L Mason |
e00945 |
my %tags; # hash of tags to be replaced
|
|
Chris L Mason |
e00945 |
my %print_tags; # hash of tags for printing to stdout
|
|
Chris L Mason |
e00945 |
my %add_tags; # hash of tags to be added if not already present
|
|
Chris L Mason |
e00945 |
my %always_add_tags; # hash of tags to be added no matter what
|
|
Chris L Mason |
2020e7 |
my %delete_tags; # tags to be deleted entirely
|
|
Chris L Mason |
e00945 |
my $new_comment; # boolean, replace comment with data read from stdin
|
|
Chris L Mason |
e00945 |
my $edit; # invoke $EDITOR when done
|
|
Chris L Mason |
ba7397 |
my $multiline; # concatenate multiline tags
|
|
Chris L Mason |
e2d213 |
my $print_comment_only; # print only the comment block
|
|
Chris L Mason |
118480 |
my $summary; # print output tags in summary form
|
|
Chris L Mason |
1028a8 |
my $guard; # pattern to use for pulling guards from the filename
|
|
Chris L Mason |
c34d28 |
my $replace_empty_comment; # new value for empty non-tag comment
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
# globals
|
|
Chris L Mason |
c08781 |
my @output_array; # the finished comment as printed
|
|
Chris L Mason |
c08781 |
my @all_tags; # array used to do final tag output
|
|
Chris L Mason |
c08781 |
my @bk_footer_tags; # holds signed-off-by and acked-by from bk
|
|
Chris L Mason |
e00945 |
my %replaced_tags; # copy of %tags so we can detect which ones are found
|
|
Chris L Mason |
e00945 |
my $replace = 0; # should we overwrite the patch file?
|
|
Chris L Mason |
e00945 |
my $outfh; # current output file handle (could be a temp file)
|
|
Chris L Mason |
e00945 |
my $infh; # current input file handle
|
|
Chris L Mason |
e00945 |
my @files; # list of all the files to be read
|
|
Chris L Mason |
e00945 |
my $input; # the current patch file we're reading
|
|
Chris L Mason |
e00945 |
my $ret;
|
|
Chris L Mason |
c34d28 |
my $tag_re = '(^[^:\s#]*):(\s+|$)(.*)';
|
|
Brandon Philips |
b2d114 |
my $git_re = '^From ([0-9a-f]{40}) .*'; # mbox From line by git format-patch
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
sub print_usage() {
|
|
Chris L Mason |
e00945 |
print STDERR "patch-tag version $VERSION\n";
|
|
Chris L Mason |
c34d28 |
print STDERR "usage: patch-tag.pl [-cePms ] [-C val] [-aAtpd tag=val] patch ...\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--print a given tag\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--comment replace the comment block with text from stdin\n";
|
|
Chris L Mason |
c34d28 |
print STDERR "\t--Comment val replace non-tag comment with val if it does not exist\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--edit invoke \$EDITOR on each file after processing\n";
|
|
Chris L Mason |
2020e7 |
print STDERR "\t--delete tag delete tag from header\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--tag tag[=value] Replace or add a given tag\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--add tag[=value] Add a tag if not already present\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--Add tag[=value] Unconditionally add a tag\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\t--add filename containing template of tags to add\n";
|
|
Chris L Mason |
ba7397 |
print STDERR "\t\t~/.patchtag will be used as a default template file\n";
|
|
Chris L Mason |
ba7397 |
print STDERR "\t--multiline concatenate multiline tags into one line\n";
|
|
Chris L Mason |
e2d213 |
print STDERR "\t--Print-comment prints only the comment block without tags\n";
|
|
Chris L Mason |
118480 |
print STDERR "\t--summary print output tags in summary form\n";
|
|
Chris L Mason |
e00945 |
print STDERR "\nAll options can be specified more than once, example\n";
|
|
Chris L Mason |
e00945 |
print STDERR "usage and additional docs at the top of this script\n";
|
|
Chris L Mason |
e00945 |
exit(1);
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
# we want the hashes of tags in lower case, normalize whatever
|
|
Chris L Mason |
e00945 |
# crud the user sent us
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
sub lc_hash(%) {
|
|
Chris L Mason |
e00945 |
my (%h) = (@_);
|
|
Chris L Mason |
e00945 |
my %lch;
|
|
Chris L Mason |
e00945 |
my $tag;
|
|
Chris L Mason |
e00945 |
my $value;
|
|
Chris L Mason |
e00945 |
foreach my $k (keys(%h)) {
|
|
Chris L Mason |
e00945 |
$tag = lc($k);
|
|
Chris L Mason |
e00945 |
$value = $h{$k};
|
|
Chris L Mason |
e00945 |
# did they use --opt "tag: value"? If so, turn it into a tag value pair
|
|
Chris L Mason |
e00945 |
if (($tag =~ m/(.+[^:]):\s*(.+)/) && $value eq "") {
|
|
Chris L Mason |
e00945 |
$tag = $1;
|
|
Chris L Mason |
e00945 |
$value = $2;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
# strip off any : in the tag
|
|
Chris L Mason |
e00945 |
$tag =~ s/://g;
|
|
Chris L Mason |
e00945 |
$lch{$tag} = $value;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
return %lch;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
ba7397 |
# check for and collect a multiline tag from the input stream
|
|
Chris L Mason |
ba7397 |
sub peek_multi_line($$$) {
|
|
Chris L Mason |
ba7397 |
my ($infh, $buf, $line) = @_;
|
|
Chris L Mason |
ba7397 |
my $next;
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
ba7397 |
$next = read_next_line($infh, $buf);
|
|
Chris L Mason |
8286d5 |
while($next =~ m/^\s/ && !($next =~ m/^\n/)) {
|
|
Chris L Mason |
ba7397 |
if ($multiline) {
|
|
Chris L Mason |
ba7397 |
chomp $line;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
$line .= $next;
|
|
Chris L Mason |
ba7397 |
$next = read_next_line($infh, $buf);
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
push @$buf, $next;
|
|
Chris L Mason |
ba7397 |
return $line;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
ba7397 |
# do tag replacement and other checks for a specific tag/value pair
|
|
Chris L Mason |
ba7397 |
# pushing it into the output tag array
|
|
Chris L Mason |
c08781 |
sub process_tag($$) {
|
|
Chris L Mason |
c08781 |
my ($t, $value) = @_;
|
|
Chris L Mason |
ba7397 |
# only do replacement on the first tag with a given key
|
|
Chris L Mason |
ba7397 |
if (defined($tags{$t}) && defined($replaced_tags{$t})) {
|
|
Chris L Mason |
ba7397 |
$value = $tags{$t};
|
|
Chris L Mason |
c08781 |
push_output_tag($t, $value);
|
|
Chris L Mason |
ba7397 |
} elsif (defined($print_tags{$t})) {
|
|
Chris L Mason |
c08781 |
push_output_tag($t, $value);
|
|
Chris L Mason |
ba7397 |
} elsif (!%print_tags) {
|
|
Chris L Mason |
c08781 |
push_output_tag($t, $value);
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
delete $replaced_tags{$t};
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
c08781 |
# tags that get pulled from bk comments get special treatment
|
|
Chris L Mason |
c08781 |
sub process_bk_tag($$) {
|
|
Chris L Mason |
c08781 |
my ($tag, $value) = @_;
|
|
Jean Delvare |
c99488 |
my $always_tags = "signed-off-by acked-by reviewed-by";
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
c08781 |
if ($always_tags =~ m/$tag/) {
|
|
Chris L Mason |
c08781 |
push @bk_footer_tags, [$tag, $value];
|
|
Chris L Mason |
c08781 |
return;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
# don't pull the bk tag out if it already exists
|
|
Chris L Mason |
c08781 |
foreach my $v (@all_tags) {
|
|
Chris L Mason |
c34d28 |
$v =~ m/$tag_re/;
|
|
Chris L Mason |
c08781 |
my $t = $1;
|
|
Chris L Mason |
c08781 |
if (lc($t) eq $tag) {
|
|
Chris L Mason |
c08781 |
return;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
$replaced_tags{$tag} = $value;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
e00945 |
# look for any tags that we were asked to print or replace from
|
|
Chris L Mason |
e00945 |
# the command line. Build the array of tags found in the comment
|
|
Chris L Mason |
ba7397 |
sub check_tags($$$) {
|
|
Chris L Mason |
ba7397 |
my ($infh, $buf, $line) = @_;
|
|
Chris L Mason |
e00945 |
my $filespec = "";
|
|
Chris L Mason |
ba7397 |
my $bk_comment = 0;
|
|
Chris L Mason |
ba7397 |
my $orig_line;
|
|
Chris L Mason |
e4801c |
my $bkold_style = 0;
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
ba7397 |
again:
|
|
Chris L Mason |
ba7397 |
$orig_line = $line;
|
|
Chris L Mason |
ba7397 |
if ($bk_comment) {
|
|
Chris L Mason |
e4801c |
$line =~ s/^#\s*//;
|
|
Chris L Mason |
ba7397 |
}
|
|
Brandon Philips |
b2d114 |
# Preserve git From line
|
|
Brandon Philips |
b2d114 |
if ($line =~ m/$git_re/) {
|
|
Brandon Philips |
b2d114 |
push @output_array, $orig_line;
|
|
Brandon Philips |
b2d114 |
$line = read_next_line($infh, $buf);
|
|
Brandon Philips |
b2d114 |
goto again;
|
|
Brandon Philips |
b2d114 |
}
|
|
Chris L Mason |
c34d28 |
if ($line =~ m/$tag_re/) {
|
|
Chris L Mason |
ba7397 |
$line = peek_multi_line($infh, $buf, $line);
|
|
Chris L Mason |
ba7397 |
# evaluate again in case the multi-line string changed
|
|
Chris L Mason |
ba7397 |
# check it as a multi line re. Clean up trailing newlines and
|
|
Chris L Mason |
ba7397 |
# ws
|
|
Chris L Mason |
ba7397 |
$line =~ s/[\s\n]*$//gs;
|
|
Chris L Mason |
ba7397 |
$line =~ m/(^[^:\s#]*):\s*(.*)/s;
|
|
Chris L Mason |
c08781 |
my $lc_tag = lc($1);
|
|
Chris L Mason |
c08781 |
my $value = $2;
|
|
Chris L Mason |
c08781 |
if ($bk_comment) {
|
|
Chris L Mason |
c08781 |
# only pull out specific tags from the bk comment stream
|
|
Chris L Mason |
c08781 |
if ($post_comment_tags =~ m/$lc_tag/) {
|
|
Chris L Mason |
c08781 |
process_bk_tag($lc_tag, $value);
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
if (!%print_tags) {
|
|
Chris L Mason |
c08781 |
push @output_array, $orig_line;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
} else {
|
|
Chris L Mason |
c08781 |
process_tag($lc_tag, $value);
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
} elsif (!%print_tags) {
|
|
Chris L Mason |
c08781 |
push @output_array, $orig_line;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
# did we find a bitkeeper style patch header?
|
|
Chris L Mason |
ba7397 |
# if so, just parse the whole thing here
|
|
Chris L Mason |
e4801c |
if ($line =~ m/^# The following is the BitKeeper ChangeSet Log/ ||
|
|
Chris L Mason |
e4801c |
$line =~ m/^# This is a BitKeeper generated diff -Nru style patch/) {
|
|
Chris L Mason |
e4801c |
# there are two bk patch styles
|
|
Chris L Mason |
e4801c |
# old:
|
|
Chris L Mason |
e4801c |
# # -------------------
|
|
Chris L Mason |
e4801c |
# # date author changset
|
|
Chris L Mason |
e4801c |
# # subject
|
|
Chris L Mason |
e4801c |
# new:
|
|
Chris L Mason |
e4801c |
# #
|
|
Chris L Mason |
e4801c |
# # Changeset
|
|
Chris L Mason |
e4801c |
# # date time author
|
|
Chris L Mason |
e4801c |
# # subject
|
|
Chris L Mason |
e4801c |
|
|
Chris L Mason |
ba7397 |
$bk_comment = 1;
|
|
Chris L Mason |
ba7397 |
my $next = read_next_line($infh, $buf);
|
|
Chris L Mason |
c08781 |
push @output_array, $next if (!%print_tags);
|
|
Chris L Mason |
e4801c |
if ($next =~ m/^# ---------/) {
|
|
Chris L Mason |
e4801c |
$bkold_style = 1;
|
|
Chris L Mason |
e4801c |
} else {
|
|
Chris L Mason |
e4801c |
# read empty line
|
|
Chris L Mason |
e4801c |
$next = read_next_line($infh, $buf);
|
|
Chris L Mason |
c08781 |
push @output_array, $next if (!%print_tags);
|
|
Chris L Mason |
e4801c |
}
|
|
Chris L Mason |
ba7397 |
$next = read_next_line($infh, $buf);
|
|
Chris L Mason |
c08781 |
push @output_array, $next if (!%print_tags);
|
|
Chris L Mason |
e4801c |
my @words = split /\s+/, $next;
|
|
Chris L Mason |
e4801c |
if ($bkold_style) {
|
|
Chris L Mason |
c08781 |
process_bk_tag('from', $words[2]);
|
|
Chris L Mason |
e4801c |
} else {
|
|
Chris L Mason |
c08781 |
process_bk_tag('from', $words[3]);
|
|
Chris L Mason |
e4801c |
}
|
|
Chris L Mason |
ba7397 |
$next = read_next_line($infh, $buf);
|
|
Chris L Mason |
c08781 |
push @output_array, $next if (!%print_tags);
|
|
Chris L Mason |
ba7397 |
chomp($next);
|
|
Chris L Mason |
e4801c |
$next =~ s/^#\s*//;
|
|
Chris L Mason |
c34d28 |
# sometimes the bk comment is empty and there is just a filename
|
|
Chris L Mason |
c34d28 |
# there's no good way to tell.
|
|
Chris L Mason |
c34d28 |
if (!($next =~ m/(.*\/)+?.*?\.(c|h|s)$/)) {
|
|
Chris L Mason |
c34d28 |
process_bk_tag('subject', $next);
|
|
Chris L Mason |
c34d28 |
}
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
ba7397 |
# we've read the from tag and subject tag, the goto again
|
|
Chris L Mason |
e4801c |
# will loop through the ChangeSet Log section looking
|
|
Chris L Mason |
ba7397 |
# for other tags
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
e4801c |
if ($bk_comment) {
|
|
Chris L Mason |
ba7397 |
$line = read_next_line($infh, $buf);
|
|
Chris L Mason |
e4801c |
# old style bk comments end with a line full of dashes
|
|
Chris L Mason |
e4801c |
# new style bk comments end with a # filename or no # at all
|
|
Chris L Mason |
e4801c |
if (($bkold_style && $line =~ m/^# --------/) ||
|
|
Chris L Mason |
e4801c |
(!$bkold_style && $line =~ m/^# \S|^[^#]/)) {
|
|
Chris L Mason |
e4801c |
push @$buf, $line;
|
|
Chris L Mason |
e4801c |
return;
|
|
Chris L Mason |
e4801c |
}
|
|
Chris L Mason |
ba7397 |
goto again;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
# print the array of tags found in the comment
|
|
Chris L Mason |
c08781 |
sub print_output_array($$) {
|
|
Chris L Mason |
79142a |
my ($input_file, $array) = @_;
|
|
Chris L Mason |
e00945 |
my $filespec = "";
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
79142a |
# if there is more then one file, include some info about which file
|
|
Chris L Mason |
79142a |
# we're printing tags from
|
|
Chris L Mason |
118480 |
if (scalar(@files) > 1 && %print_tags && !$summary) {
|
|
Chris L Mason |
e00945 |
$filespec = "$input_file: ";
|
|
Chris L Mason |
118480 |
} elsif ($summary) {
|
|
Chris L Mason |
118480 |
$filespec = "# ";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
79142a |
foreach my $s (@$array) {
|
|
Chris L Mason |
118480 |
if ($summary) {
|
|
Chris L Mason |
118480 |
$s =~ s/\n\s/\n#\t/mg;
|
|
Chris L Mason |
118480 |
}
|
|
Chris L Mason |
c08781 |
print $outfh "${filespec}$s";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
118480 |
if ($summary) {
|
|
Chris L Mason |
118480 |
print $outfh "$input_file\n\n";
|
|
Chris L Mason |
118480 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
# for -a and -A, look for a filename as an arg instead of a tag. If found
|
|
Chris L Mason |
e00945 |
# fill in the hash with the contents of the file
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
e00945 |
sub fill_hash_from_file($) {
|
|
Chris L Mason |
e00945 |
my ($h) = @_;
|
|
Chris L Mason |
e00945 |
# look for tags to add either from the command line or template files
|
|
Chris L Mason |
e00945 |
if (%$h && keys(%$h) <= 1) {
|
|
Chris L Mason |
e00945 |
my ($k, $v) = each %$h;
|
|
Chris L Mason |
e00945 |
my $source;
|
|
Chris L Mason |
e00945 |
if (defined($k) && (!defined($v) || $v eq "")) {
|
|
Chris L Mason |
e00945 |
if (-f $k) {
|
|
Chris L Mason |
e00945 |
delete($h->{$k});
|
|
Chris L Mason |
e00945 |
$source = $k;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
if (defined($source)) {
|
|
Chris L Mason |
e00945 |
print STDERR "Using $source as tag template source\n";
|
|
Chris L Mason |
e00945 |
# delete($$h{$k});
|
|
Chris L Mason |
e00945 |
my $template = new IO::File;
|
|
Chris L Mason |
e00945 |
$template->open("<$source") || die "Unable to open $source for reading";
|
|
Chris L Mason |
e00945 |
while(<$template>) {
|
|
Chris L Mason |
e00945 |
# eat comments
|
|
Chris L Mason |
e00945 |
s/#.*//;
|
|
Chris L Mason |
e00945 |
# eat ws at the start of the line
|
|
Chris L Mason |
e00945 |
s/^\s//;
|
|
Chris L Mason |
c34d28 |
if (m/$tag_re/) {
|
|
Chris L Mason |
c34d28 |
$h->{lc($1)} = $3;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
$template->close();
|
|
Chris L Mason |
79142a |
return 1;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
79142a |
return 0;
|
|
Chris L Mason |
79142a |
}
|
|
Chris L Mason |
79142a |
|
|
Chris L Mason |
79142a |
# helper function to pick the proper output array for the tags
|
|
Chris L Mason |
79142a |
# some go before the comment block and some go after
|
|
Chris L Mason |
c5851a |
# send $allow_dup = 0 if you want to prevent duplicate tag names.
|
|
Chris L Mason |
c5851a |
# Completely duplicate tag name,value pairs are always removed.
|
|
Chris L Mason |
c08781 |
sub push_output_tag($$) {
|
|
Chris L Mason |
c08781 |
my ($tag, $value) = @_;
|
|
Chris L Mason |
c5851a |
my $uc_tag = ucfirst($tag);
|
|
Chris L Mason |
c5851a |
my $string = $uc_tag . ": $value";
|
|
Chris L Mason |
2020e7 |
# check against the delete hash
|
|
Chris L Mason |
2020e7 |
if (defined($delete_tags{$tag})) {
|
|
Chris L Mason |
2020e7 |
return;
|
|
Chris L Mason |
2020e7 |
}
|
|
Chris L Mason |
ba7397 |
# check for dups;
|
|
Chris L Mason |
c08781 |
foreach my $v (@all_tags) {
|
|
Chris L Mason |
ba7397 |
if ($v eq $string) {
|
|
Chris L Mason |
ba7397 |
return;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
79142a |
}
|
|
Chris L Mason |
c08781 |
push @all_tags, $string;
|
|
Chris L Mason |
c08781 |
push @output_array, "$string\n";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
ba7397 |
# helper function to cherry pick output tags from a hash.
|
|
Chris L Mason |
79142a |
# This is used to print the From and Subject Tags first.
|
|
Chris L Mason |
e00945 |
sub add_output_tag ($$) {
|
|
Chris L Mason |
e00945 |
my ($tag, $h) = @_;
|
|
Chris L Mason |
c08781 |
my $value;
|
|
Chris L Mason |
c08781 |
my $tag_end = 0;
|
|
Chris L Mason |
c08781 |
my $line;
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
c08781 |
if (!defined($$h{$tag})) {
|
|
Chris L Mason |
c08781 |
return;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
$value = $$h{$tag};
|
|
Chris L Mason |
c08781 |
delete($$h{$tag});
|
|
Chris L Mason |
c08781 |
# for post comment tags, just tack it onto the very end.
|
|
Chris L Mason |
c08781 |
if ($post_comment_tags =~ m/$tag/) {
|
|
Chris L Mason |
c08781 |
process_tag($tag, $value);
|
|
Chris L Mason |
c08781 |
return;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
c08781 |
# find the end of the top tag section in the comment.
|
|
Chris L Mason |
c08781 |
foreach $line (@output_array) {
|
|
Brandon Philips |
b2d114 |
# Account git From line as tag header
|
|
Brandon Philips |
b2d114 |
if ($line =~ m/$git_re/) {
|
|
Brandon Philips |
b2d114 |
$tag_end++;
|
|
Brandon Philips |
b2d114 |
} elsif ($line =~ m/$tag_re/) {
|
|
Chris L Mason |
c08781 |
my $t = lc($1);
|
|
Chris L Mason |
c08781 |
# did we find our way into the post comment tag section?
|
|
Chris L Mason |
c08781 |
if ($post_comment_tags =~ m/$t/) {
|
|
Chris L Mason |
c08781 |
last;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
$tag_end++;
|
|
Chris L Mason |
c08781 |
} else {
|
|
Chris L Mason |
c08781 |
last;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
c08781 |
my @tmp_array = @output_array[$tag_end .. scalar(@output_array)-1];
|
|
Chris L Mason |
c08781 |
$#output_array = $tag_end - 1;
|
|
Chris L Mason |
c08781 |
process_tag($tag, $value);
|
|
Chris L Mason |
c08781 |
push @output_array, @tmp_array;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
c08781 |
# from the much harder then it should be category. Walk the
|
|
Chris L Mason |
c08781 |
# comment block and divide it into three parts. Header, comment,
|
|
Chris L Mason |
c08781 |
# footer. Make sure each part is separated by no more then one
|
|
Chris L Mason |
c08781 |
# blank line.
|
|
Chris L Mason |
c08781 |
#
|
|
Chris L Mason |
c08781 |
sub cleanup_blank_lines($) {
|
|
Chris L Mason |
c08781 |
my ($ar) = @_;
|
|
Chris L Mason |
c08781 |
my $line;
|
|
Chris L Mason |
c08781 |
my $tag_end;
|
|
Chris L Mason |
c08781 |
my $footer_start;
|
|
Chris L Mason |
c08781 |
my @header_ar = ();
|
|
Chris L Mason |
c08781 |
my @comment_ar = ();
|
|
Chris L Mason |
c08781 |
my @footer_ar = ();
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
c08781 |
# find the header
|
|
Chris L Mason |
c08781 |
foreach $line (@$ar) {
|
|
Chris L Mason |
c34d28 |
if ($line =~ m/$tag_re/) {
|
|
Chris L Mason |
c08781 |
my $t = lc($1);
|
|
Chris L Mason |
c08781 |
# did we find our way into the post comment tag section?
|
|
Chris L Mason |
c08781 |
if ($post_comment_tags =~ m/$t/) {
|
|
Chris L Mason |
c08781 |
last;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
$tag_end++;
|
|
Chris L Mason |
c08781 |
} else {
|
|
Chris L Mason |
c08781 |
last;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
if ($tag_end) {
|
|
Chris L Mason |
c08781 |
@header_ar = @$ar[0 .. $tag_end-1];
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
# eat all the blank lines
|
|
Chris L Mason |
c08781 |
while($tag_end < scalar(@$ar)) {
|
|
Chris L Mason |
c08781 |
$line = $$ar[$tag_end];
|
|
Chris L Mason |
c08781 |
if ($line =~ m/^\s*\n$/) {
|
|
Chris L Mason |
c08781 |
$tag_end++;
|
|
Chris L Mason |
c08781 |
} else {
|
|
Chris L Mason |
c08781 |
last;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
# $tag_end is now the start of the comment block.
|
|
Chris L Mason |
c08781 |
# pop ws off the end of the output array;
|
|
Chris L Mason |
c08781 |
while($$ar[scalar(@$ar)-1] =~ m/^\s*\n$/) {
|
|
Chris L Mason |
c08781 |
my $t = pop @$ar;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
c08781 |
# walk up the array to find the end of the footer.
|
|
Chris L Mason |
c08781 |
for($footer_start = scalar(@$ar) - 1 ; $footer_start >= $tag_end;
|
|
Chris L Mason |
c08781 |
$footer_start--) {
|
|
Chris L Mason |
c08781 |
$line = $ar->[$footer_start];
|
|
Chris L Mason |
c34d28 |
if (!($line =~ m/$tag_re/)) {
|
|
Chris L Mason |
c08781 |
last;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
@footer_ar = @$ar[$footer_start+1 .. scalar(@$ar)-1];
|
|
Chris L Mason |
c08781 |
# eat ws between the comment and the footer
|
|
Chris L Mason |
c08781 |
while($footer_start > $tag_end &&
|
|
Chris L Mason |
c08781 |
$ar->[$footer_start] =~ m/^\s*\n$/) {
|
|
Chris L Mason |
c08781 |
$footer_start--;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
|
|
Chris L Mason |
c08781 |
@comment_ar = @$ar[$tag_end .. $footer_start];
|
|
Chris L Mason |
c08781 |
if ($print_comment_only) {
|
|
Chris L Mason |
c08781 |
@$ar = @comment_ar;
|
|
Chris L Mason |
c08781 |
return;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c34d28 |
if (defined($replace_empty_comment) && scalar(@comment_ar) == 0) {
|
|
Chris L Mason |
c34d28 |
push @comment_ar, "$replace_empty_comment\n";
|
|
Chris L Mason |
c34d28 |
}
|
|
Chris L Mason |
c08781 |
@$ar = @header_ar;
|
|
Chris L Mason |
c08781 |
if (scalar(@comment_ar)) {
|
|
Chris L Mason |
c08781 |
if (scalar(@header_ar)) {
|
|
Chris L Mason |
c08781 |
push @$ar, "\n";
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
push @$ar, @comment_ar;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
if (scalar(@footer_ar)) {
|
|
Chris L Mason |
c08781 |
push @$ar, "\n";
|
|
Chris L Mason |
c08781 |
push @$ar, @footer_ar;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
if ($replace) {
|
|
Chris L Mason |
c08781 |
push @$ar, "\n";
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
ba7397 |
# read a line from $fh, using anything queued up in @$buf first
|
|
Chris L Mason |
ba7397 |
#
|
|
Chris L Mason |
ba7397 |
sub read_next_line($$) {
|
|
Chris L Mason |
ba7397 |
my ($fh, $buf) = @_;
|
|
Chris L Mason |
ba7397 |
my $line;
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
ba7397 |
$line = pop @$buf;
|
|
Chris L Mason |
ba7397 |
if (!defined($line)) {
|
|
Chris L Mason |
ba7397 |
$line = $fh->getline();
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
return $line;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
ba7397 |
# diff reading state machine. When it returns a state of "done"
|
|
Chris L Mason |
ba7397 |
# that means the line is the start of the diff. Any state other then
|
|
Chris L Mason |
ba7397 |
# "comment" might be the start of the diff, the only way to know for
|
|
Chris L Mason |
ba7397 |
# sure is to check the following line.
|
|
Chris L Mason |
ba7397 |
#
|
|
Chris L Mason |
ba7397 |
sub process_line($$) {
|
|
Chris L Mason |
ba7397 |
my ($line, $state) = @_;
|
|
Chris L Mason |
ba7397 |
my $return_state = "";
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
ba7397 |
# bk uses this: ===== fs/reiserfs/inode.c 1.49 vs 1.50 =====
|
|
Chris L Mason |
ba7397 |
if ($line =~ m/(^Index:)|(^=====.*vs.*=====$)/) {
|
|
Chris L Mason |
ba7397 |
$return_state = "index";
|
|
Chris L Mason |
ba7397 |
} elsif ($line =~ m/^=================/ && $state eq "index") {
|
|
Chris L Mason |
ba7397 |
$return_state = "done";
|
|
Chris L Mason |
ba7397 |
} elsif ($line =~ m/^diff/) {
|
|
Chris L Mason |
ba7397 |
$return_state = "diff";
|
|
Chris L Mason |
ba7397 |
} elsif ($line =~ m/(^---)|(^\+\+\+)/) {
|
|
Chris L Mason |
ba7397 |
$return_state = "done";
|
|
Chris L Mason |
ba7397 |
} elsif ($state ne "comment") {
|
|
Chris L Mason |
ba7397 |
$return_state = "comment";
|
|
Chris L Mason |
ba7397 |
} else {
|
|
Chris L Mason |
ba7397 |
$return_state = "comment";
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
return $return_state;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
|
|
Chris L Mason |
e00945 |
$ret = GetOptions("add:s%" => \%add_tags,
|
|
Chris L Mason |
e00945 |
"Add:s%" => \%always_add_tags,
|
|
Chris L Mason |
2020e7 |
"delete:s%" => \%delete_tags,
|
|
Chris L Mason |
e00945 |
"edit" => \$edit,
|
|
Chris L Mason |
1028a8 |
"guard=s" => \$guard,
|
|
Chris L Mason |
e00945 |
"tag:s%" => \%tags,
|
|
Chris L Mason |
e00945 |
"print:s" => \%print_tags,
|
|
Chris L Mason |
e2d213 |
"Print-comment" => \$print_comment_only,
|
|
Chris L Mason |
e00945 |
"comment" => \$new_comment,
|
|
Chris L Mason |
c34d28 |
"Comment=s" => \$replace_empty_comment,
|
|
Chris L Mason |
ba7397 |
"multiline" => \$multiline,
|
|
Chris L Mason |
118480 |
"summary" => \$summary,
|
|
Chris L Mason |
e00945 |
) || print_usage();
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
@files = @ARGV;
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
if (scalar(@ARGV) < 1) {
|
|
Chris L Mason |
e00945 |
print_usage();
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
if ($new_comment && scalar(@ARGV) > 1) {
|
|
Chris L Mason |
e00945 |
print STDERR "error: --comment can only be used on one file at a time\n";
|
|
Chris L Mason |
e00945 |
print_usage();
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
fill_hash_from_file(\%add_tags);
|
|
Chris L Mason |
e00945 |
fill_hash_from_file(\%always_add_tags);
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
118480 |
if ($summary && !%print_tags) {
|
|
Chris L Mason |
118480 |
$print_tags{'subject'} = 1;
|
|
Chris L Mason |
118480 |
$print_tags{'references'} = 1;
|
|
Chris L Mason |
118480 |
$print_tags{'suse-bugzilla'} = 1;
|
|
Chris L Mason |
118480 |
}
|
|
Chris L Mason |
118480 |
|
|
Chris L Mason |
79142a |
# if we're in edit mode and no tags are provided, check for a default
|
|
Chris L Mason |
79142a |
# template file.
|
|
Chris L Mason |
79142a |
if ($edit && keys(%tags) == 0 && keys(%add_tags) == 0 &&
|
|
Chris L Mason |
79142a |
keys(%always_add_tags) == 0 &&
|
|
Chris L Mason |
79142a |
-r "$ENV{'HOME'}/.patchtag") {
|
|
Chris L Mason |
79142a |
$add_tags{"$ENV{'HOME'}/.patchtag"} = "";
|
|
Chris L Mason |
79142a |
fill_hash_from_file(\%add_tags);
|
|
Chris L Mason |
79142a |
}
|
|
Chris L Mason |
79142a |
|
|
Chris L Mason |
e00945 |
# never overwrite the original when --print is used
|
|
Chris L Mason |
e00945 |
#
|
|
Chris L Mason |
2020e7 |
if ((%add_tags || %always_add_tags || %tags ||
|
|
Chris L Mason |
c34d28 |
$new_comment || $edit || %delete_tags || $replace_empty_comment) &&
|
|
Chris L Mason |
e2d213 |
!(%print_tags || $print_comment_only)) {
|
|
Chris L Mason |
e00945 |
$replace = 1;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
%tags = lc_hash(%tags);
|
|
Chris L Mason |
e00945 |
%print_tags = lc_hash(%print_tags);
|
|
Chris L Mason |
e00945 |
%add_tags = lc_hash(%add_tags);
|
|
Chris L Mason |
e00945 |
%always_add_tags = lc_hash(%always_add_tags);
|
|
Chris L Mason |
2020e7 |
%delete_tags = lc_hash(%delete_tags);
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
# if we're editing setup the default tags
|
|
Chris L Mason |
79142a |
if ($edit && keys(%add_tags) == 0) {
|
|
Chris L Mason |
e00945 |
my @words = split /:/, $default_comment;
|
|
Chris L Mason |
e00945 |
foreach my $w (@words) {
|
|
Chris L Mason |
79142a |
$add_tags{$w} = "";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
1028a8 |
foreach my $guarded_input (@files) {
|
|
Chris L Mason |
e00945 |
my $last = "";
|
|
Chris L Mason |
ba7397 |
my $scan_state = "comment";
|
|
Chris L Mason |
ba7397 |
my @input_buffer = ();
|
|
Chris L Mason |
1028a8 |
my $input;
|
|
Chris L Mason |
1028a8 |
|
|
Chris L Mason |
1028a8 |
if ($summary && $guard && $guarded_input =~ m/($guard)(.+)/) {
|
|
Chris L Mason |
1028a8 |
$input = $2;
|
|
Chris L Mason |
1028a8 |
} else {
|
|
Chris L Mason |
1028a8 |
$input = $guarded_input;
|
|
Chris L Mason |
1028a8 |
}
|
|
Chris L Mason |
e00945 |
$infh = new IO::File;
|
|
Chris L Mason |
e00945 |
$infh->open("<$input") || die "Unable to open $input for reading";
|
|
Chris L Mason |
e00945 |
%replaced_tags = (%tags, %add_tags);
|
|
Chris L Mason |
c08781 |
@all_tags = ();
|
|
Chris L Mason |
c08781 |
@output_array = ();
|
|
Chris L Mason |
c08781 |
@bk_footer_tags = ();
|
|
Chris L Mason |
c34d28 |
my %tmp_always_add = %always_add_tags;
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
if ($replace) {
|
|
Chris L Mason |
e00945 |
$outfh = new File::Temp(TEMPLATE => "$input.XXXXXX", UNLINK => 0) ||
|
|
Chris L Mason |
e00945 |
die "Unable to create temp file";
|
|
Chris L Mason |
e00945 |
} else {
|
|
Chris L Mason |
e00945 |
$outfh = new IO::File;
|
|
Chris L Mason |
e00945 |
$outfh->open(">-") || die "Unable to open stdout";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
|
|
Chris L Mason |
e00945 |
# loop through until the start of the diff.
|
|
Chris L Mason |
ba7397 |
while($_ = read_next_line($infh, \@input_buffer)) {
|
|
Chris L Mason |
ba7397 |
$scan_state = process_line($_, $scan_state);
|
|
Chris L Mason |
ba7397 |
if ($scan_state eq "done") {
|
|
Chris L Mason |
ba7397 |
push @input_buffer, $_;
|
|
Chris L Mason |
e00945 |
last;
|
|
Chris L Mason |
ba7397 |
}
|
|
Chris L Mason |
ba7397 |
if ($scan_state ne "comment") {
|
|
Chris L Mason |
ba7397 |
my $next = read_next_line($infh, \@input_buffer);
|
|
Chris L Mason |
ba7397 |
$scan_state = process_line($next, $scan_state);
|
|
Chris L Mason |
ba7397 |
if ($scan_state ne "comment") {
|
|
Chris L Mason |
ba7397 |
push @input_buffer, $next;
|
|
Chris L Mason |
ba7397 |
push @input_buffer, $_;
|
|
Chris L Mason |
ba7397 |
last;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
ba7397 |
push @input_buffer, $next;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
ba7397 |
check_tags($infh, \@input_buffer, $_);
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
c08781 |
# pop ws off the end of the output array;
|
|
Chris L Mason |
c08781 |
while($output_array[scalar(@output_array)-1] =~ m/^\s*\n$/) {
|
|
Chris L Mason |
c08781 |
pop @output_array;
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
c08781 |
foreach my $h (@bk_footer_tags) {
|
|
Chris L Mason |
c08781 |
process_tag($h->[0], $h->[1]);
|
|
Chris L Mason |
c08781 |
}
|
|
Chris L Mason |
e00945 |
# add any new tags left over, but do From and Subject first
|
|
Chris L Mason |
e00945 |
add_output_tag('from', \%replaced_tags);
|
|
Chris L Mason |
e00945 |
add_output_tag('subject', \%replaced_tags);
|
|
Chris L Mason |
e00945 |
foreach my $h (sort(keys(%replaced_tags))) {
|
|
Chris L Mason |
79142a |
add_output_tag($h, \%replaced_tags);
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
# add any of the tags from -A
|
|
Chris L Mason |
c34d28 |
foreach my $h (sort(keys(%tmp_always_add))) {
|
|
Chris L Mason |
c34d28 |
add_output_tag($h, \%tmp_always_add);
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
# replace the comment entirely for -c
|
|
Chris L Mason |
e00945 |
if ($new_comment) {
|
|
Chris L Mason |
e00945 |
while(<STDIN>) {
|
|
Chris L Mason |
e00945 |
print $outfh $_;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
} else {
|
|
Chris L Mason |
c08781 |
cleanup_blank_lines(\@output_array);
|
|
Chris L Mason |
c08781 |
print_output_array($guarded_input, \@output_array);
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
# in replace mode, copy our temp file over the original.
|
|
Chris L Mason |
e00945 |
if ($replace) {
|
|
Chris L Mason |
ba7397 |
while($_ = read_next_line($infh, \@input_buffer)) {
|
|
Chris L Mason |
e00945 |
print $outfh $_;
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
unlink "$input" || die "Unable to unlink $input";
|
|
Chris L Mason |
e00945 |
rename $outfh->filename, $input ||
|
|
Chris L Mason |
e00945 |
die "Unable to rename $outfh->filename to $input";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
if ($edit) {
|
|
Chris L Mason |
e00945 |
my $editor = "vi";
|
|
Chris L Mason |
e00945 |
if (defined($ENV{'EDITOR'})) {
|
|
Chris L Mason |
e00945 |
$editor = $ENV{'EDITOR'};
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
$ret = system("$editor $input");
|
|
Chris L Mason |
e00945 |
if ($ret) {
|
|
Chris L Mason |
e00945 |
$ret = $ret >> 8;
|
|
Chris L Mason |
e00945 |
print STDERR "warning $editor exited with $ret\n";
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
}
|
|
Chris L Mason |
e00945 |
$infh->close();
|
|
Chris L Mason |
e00945 |
$outfh->close();
|
|
Chris L Mason |
e00945 |
}
|