| #!/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; |