|  | #!/usr/bin/perl -w | 
|  | # | 
|  | # genpatch - A utility that generates patches for submission to | 
|  | # wine-patches@winehq.org | 
|  | # | 
|  | # Copyright Steven Elliott <elliotsl@mindspring.com> | 
|  | # | 
|  | # This library is free software; you can redistribute it and/or | 
|  | # modify it under the terms of the GNU Lesser General Public | 
|  | # License as published by the Free Software Foundation; either | 
|  | # version 2.1 of the License, or (at your option) any later version. | 
|  | # | 
|  | # This library is distributed in the hope that it will be useful, | 
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | # Lesser General Public License for more details. | 
|  | # | 
|  | # You should have received a copy of the GNU Lesser General Public | 
|  | # License along with this library; if not, write to the Free Software | 
|  | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | # | 
|  |  | 
|  | =head1 NAME | 
|  |  | 
|  | genpatch - A utility that generates patches for submission to | 
|  | wine-patches@winehq.org | 
|  |  | 
|  | =head1 SYNOPSIS | 
|  |  | 
|  | genpatch [B<-v>] [B<-n> patch_name] [B<-f> patch_file] | 
|  | [B<-c> change_log] [B<-m> modified_files] | 
|  | [B<-a> added_files] | 
|  |  | 
|  | =head1 DESCRIPTION | 
|  |  | 
|  | The genpatch utility generated patches for submission to | 
|  | wine-patches@winehq by acting as a wrapper to "cvs diff".  The "B<-v>" | 
|  | switch specifies that verbose output should be generated.  The "B<-n>" | 
|  | switch overrides the patch name ("Name" field) which defaults to a | 
|  | numeric UTC date.  The "B<-f>" switch overrides the filename of the patch | 
|  | which defaults to "patches/<patch_name>.diff".  The "B<-c>" switch | 
|  | specifies the CVS change log entry ("ChangeLog" field) which can be | 
|  | seen when "cvs log" is invoked.  The "B<-m>" ("ModifiedFiles" field) and | 
|  | "B<-a>" ("AddedFiles" field) switches override the set of files that | 
|  | would normally be included by the "cvs diff".  Normally "cvs diff" | 
|  | includes all files modified relative to the deltas indicated by the | 
|  | "CVS/Entries" file and ignores all newly added files.  The "B<-m>" switch | 
|  | specifies a whitespace separated list of files that were modified. | 
|  | The "B<-a>" switch specifies a whitespace separated list of files that | 
|  | were added. | 
|  |  | 
|  | =head1 EXAMPLE | 
|  |  | 
|  | genpatch B<-n> NLSFix B<-c> "various fixes for NLS support" \ | 
|  | B<-m> ole/ole2nls.c B<-a> ole/ole3nls.c | 
|  |  | 
|  | The above generates a patch named "NLSFix" in "patches/NLSFix.diff" | 
|  | that includes a modification to "ole/ole2nls.c" and a newly added | 
|  | "ole/ole3nls.c". | 
|  |  | 
|  | =cut | 
|  |  | 
|  | use strict; | 
|  |  | 
|  | use Getopt::Std; | 
|  | use File::Basename; | 
|  | use POSIX qw(strftime); | 
|  |  | 
|  | # Command line options | 
|  | my %options; | 
|  |  | 
|  | # Default the patch name to the UTC time.  Use a more descriptive date for the | 
|  | # patch generation date. | 
|  | $options{n} = strftime "%Y%m%d%H%M", gmtime; | 
|  | my $gen_date = strftime "%Y/%m/%d %H:%M:%S UTC", gmtime; | 
|  |  | 
|  | unless(getopts("vn:f:c:m:a:p:", \%options)) | 
|  | { | 
|  | print STDERR "Usage: $0 [-v] [-n patch_name] [-f patch_file] " . | 
|  | "[-c change_log] [-m modified_files] [-a added_files] [-p path_to_patches]\n"; | 
|  | exit 1; | 
|  | } | 
|  |  | 
|  | $options{p} = "patches" if (!defined $options{p}); | 
|  | $options{f} = "$options{p}/$options{n}.diff" if (!defined $options{f}); | 
|  | $options{p} = dirname $options{f}; | 
|  | $options{a} = "" if (!defined $options{a}); | 
|  | my @added_files = split ' ', $options{a}; | 
|  | $options{m} = "" if (!defined $options{m}); | 
|  | $options{c} = ""  if (!defined $options{c}); | 
|  | $options{c} =~ s/\\n/\n\t/g; | 
|  |  | 
|  | if (!-d $options{p}) | 
|  | { | 
|  | mkdir $options{p}, (0777 & ~umask) | 
|  | or die "Unable to mkdir $options{p}: $!"; | 
|  | } | 
|  | elsif (-e $options{f}) | 
|  | { | 
|  | print STDERR "$options{f} already exists.  Aborting.\n"; | 
|  | exit 1; | 
|  | } | 
|  |  | 
|  | my $mod_files_str = $options{m} ? $options{m} : "<see cvs diff>"; | 
|  | print "Generating $options{f}.\n" if($options{v}); | 
|  | open OPT_F, ">$options{f}" or die "Unable to open $options{f} for write: $!"; | 
|  | print OPT_F <<EOF; | 
|  | Name: $options{n} | 
|  | ChangeLog: $options{c} | 
|  | GenDate: $gen_date | 
|  | ModifiedFiles: $mod_files_str | 
|  | AddedFiles: $options{a} | 
|  | EOF | 
|  |  | 
|  | print "Invoking cvs diff.\n" if($options{v}); | 
|  | open CVS_IN, "cvs diff -u $options{m} |" | 
|  | or die "Unable to invoke cvs: $!"; | 
|  | while (my $cvs_line = <CVS_IN>) | 
|  | { | 
|  | if ($cvs_line !~ /^\? (.*)/) | 
|  | { | 
|  | print OPT_F $cvs_line; | 
|  | } | 
|  | elsif (!$options{a}) | 
|  | { | 
|  | push @added_files, chomp $1; | 
|  | } | 
|  | } | 
|  | close CVS_IN; | 
|  |  | 
|  | foreach my $added_file (@added_files) | 
|  | { | 
|  | print "Adding $added_file as a new file.\n" if($options{v}); | 
|  | open DIFF_IN, "diff -u /dev/null $added_file|" | 
|  | or die "Unable to invoke diff: $!"; | 
|  | print OPT_F <DIFF_IN>; | 
|  | close DIFF_IN; | 
|  | } | 
|  |  | 
|  | close OPT_F; |