| #!/usr/bin/perl |
| # |
| # genpatch - A utility that generates patches for submission to |
| # wine-patches@winehq.com |
| # |
| # 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.com |
| |
| =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); |
| |
| my $gen_date; # date the patch was generated |
| my %options; # command line options |
| my @modified_files; # optional list of files that were modified |
| my @added_files; # added files as an array |
| my $added_file; # added file being considered |
| my $cvs_line; # line of output from CVS |
| my $mod_files_str; # string that describes the modified files |
| |
| # 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; |
| $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" unless(exists $options{p}); |
| $options{f} = "$options{p}/$options{n}.diff" unless(exists $options{f}); |
| $options{p} = dirname $options{f}; |
| @added_files = split ' ', $options{a}; |
| @modified_files = split ' ', $options{m}; |
| $options{c} =~ s/\\n/\n\t/g; |
| |
| if(-d $options{p}) |
| { |
| if(-e $options{f}) |
| { |
| print STDERR "$options{f} already exists. Aborting.\n"; |
| exit 1; |
| } |
| } |
| else |
| { |
| mkdir $options{p}, (0777 & ~umask) or |
| die "Unable to mkdir $options{p}: $!"; |
| } |
| |
| $mod_files_str = exists($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 @modified_files|" or die "Unable to invoke cvs: $!"; |
| while($cvs_line = <CVS_IN>) |
| { |
| chomp $cvs_line; |
| if($cvs_line =~ /^\? (.*)/) |
| { |
| push @added_files, $1 unless(exists $options{a}); |
| } |
| else |
| { |
| print OPT_F <CVS_IN>; |
| } |
| } |
| close CVS_IN; |
| |
| foreach $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; |