genpatch 4.34 KB
Newer Older
1
#!/usr/bin/perl -w
2
#
3
# genpatch - A utility that generates patches for submission to
4
# wine-patches@winehq.org
5
#
6 7 8 9 10 11 12 13 14 15 16 17 18 19
# 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
20
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22
#

23 24 25
=head1 NAME

genpatch - A utility that generates patches for submission to
26
wine-patches@winehq.org
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

=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;

65 66 67 68
use Getopt::Std;
use File::Basename;
use POSIX qw(strftime);

69 70
# Command line options
my %options;
71 72 73 74

# 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;
75
my $gen_date = strftime "%Y/%m/%d %H:%M:%S UTC", gmtime;
76

77
unless(getopts("vn:f:c:m:a:p:", \%options))
78
{
79
    print STDERR "Usage: $0 [-v] [-n patch_name] [-f patch_file] " .
80
        "[-c change_log] [-m modified_files] [-a added_files] [-p path_to_patches]\n";
81 82 83
    exit 1;
}

84 85
$options{p} = "patches" if (!defined $options{p});
$options{f} = "$options{p}/$options{n}.diff" if (!defined $options{f});
86
$options{p} = dirname $options{f};
87 88 89 90
$options{a} = "" if (!defined $options{a});
my @added_files = split ' ', $options{a};
$options{m} = "" if (!defined $options{m});
$options{c} = ""  if (!defined $options{c});
91
$options{c} =~ s/\\n/\n\t/g;
92

93
if (!-d $options{p})
94
{
95 96
    mkdir $options{p}, (0777 & ~umask)
    or die "Unable to mkdir $options{p}: $!";
97
}
98
elsif (-e $options{f})
99
{
100 101
    print STDERR "$options{f} already exists.  Aborting.\n";
    exit 1;
102 103
}

104
my $mod_files_str = $options{m} ? $options{m} : "<see cvs diff>";
105
print "Generating $options{f}.\n" if($options{v});
106 107 108 109 110
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
111 112
ModifiedFiles: $mod_files_str
AddedFiles: $options{a}
113 114
EOF

115
print "Invoking cvs diff.\n" if($options{v});
116 117 118
open CVS_IN, "cvs diff -u $options{m} |"
or die "Unable to invoke cvs: $!";
while (my $cvs_line = <CVS_IN>)
119
{
120
    if ($cvs_line !~ /^\? (.*)/)
121
    {
122
        print OPT_F $cvs_line;
123
    }
124
    elsif (!$options{a})
125
    {
126
        push @added_files, chomp $1;
127 128 129 130
    }
}
close CVS_IN;

131
foreach my $added_file (@added_files)
132 133
{
    print "Adding $added_file as a new file.\n" if($options{v});
134 135
    open DIFF_IN, "diff -u /dev/null $added_file|"
    or die "Unable to invoke diff: $!";
136 137 138 139
    print OPT_F <DIFF_IN>;
    close DIFF_IN;
}

140
close OPT_F;