#!/usr/bin/perl -w # Convert from a ptools XFS/DMAPI mod to a git changeset. # # Adds in two "Signed-off-by:" lines now also, one for the person # who commits the mod, and one for the person running this script # (unless they're the same). # # If mod description has any #-prefixed lines, those are now used # to keep Signed-off-by: (Acked-by:, ...) lines around (ie. so we # better keep track of the code flow from non-SGI folks. Used to # be done by hand. # # Uses quilt to store the patches from the mods and so that # if the patch doesn't apply then we have a nice enviroment to # modify the patch # The code will use the patch in patches subdir if it exists, # so if you don't want this then delete the patch. # use strict; use Text::Wrap; use File::Basename; unshift @INC, "/home/$ENV{'USER'}/bin"; require 'developers.pl'; if ($#ARGV != 1) { print STDERR "Usage: p_mod2git \n"; exit 1; } if (!defined($ENV{'WORKAREA'})) { print STDERR "Error: WORKAREA must be set to workarea for \n"; exit 1; } my $GIT_TREE = $ARGV[0]; my $MODID = $ARGV[1]; my $TREEID = $ARGV[1]; my $MODNUMBER = $ARGV[1]; $MODNUMBER =~ s/(\S+):(\S+):(\S+)/$3/g; my $CWD = $ENV{'PWD'}; # # Find kernel version (if its a kernel), then create patch file name by # plucking a prefix from modid - X:dmapi:Y, X:xfs-kern:Y or xfs-cmds:X:Y # then appending the mod number and the one-line-summary. # my $KERNEL = 0; if ( -d "$GIT_TREE/fs/xfs/linux-2.4" ) { $KERNEL = 2.4; } elsif ( -d "$GIT_TREE/fs/xfs/linux-2.6" ) { $KERNEL = 2.6; } if ($KERNEL == 0) { # xfs-cmds $TREEID =~ s/(\S+):(\S+):(\S+)/$1/g; print "Target: non-kernel tree\n"; } else { # xfs-kern/dmapi $TREEID =~ s/(\S+):(\S+):(\S+)/$2/g; print "Target: $KERNEL kernel tree\n"; } # the patch file for the mod my $MODPATCH = 'git-' . $TREEID . '-' . $MODNUMBER; my $SUMMARY = $CWD . '/' . $MODPATCH; my $QUILTPATCH = $GIT_TREE . '/patches/' . $MODPATCH; my $AUTHOR = &developers::author('.', $MODID); # Set some environment variables for git my $MODSIGN = &developers::developer($AUTHOR); my $OWNSIGN = &developers::developer($ENV{'USER'}); $ENV{'GIT_AUTHOR_NAME'} = &developers::developer_name($AUTHOR); $ENV{'GIT_AUTHOR_EMAIL'} = &developers::developer_email($AUTHOR); $ENV{'GIT_COMMITTER_NAME'} = &developers::developer_name($ENV{'USER'}); $ENV{'GIT_COMMITTER_EMAIL'} = &developers::developer_email($ENV{'USER'}); # Create patch file and input stream from p_modinfo open MODINFO, "p_modinfo -b -H PV,Description $MODID |" or die "modinfo"; my $PVNUMBER = ; $PVNUMBER =~ s/(\d+).*\n/$1/; # Create the changeset description undef $/; my $DESCRIPTION = '[XFS] ' . ; $/ = "\n"; close MODINFO; my %REVIEWERS = &developers::reviewers('.', $MODID); # extract existing signed-off-by clauses my @desc = split(/\n/, $DESCRIPTION); my @DESC = grep(!/^Signed-off-by/, @desc); my @SIGN = grep(/^(Signed-off|Acked)-by/, @desc); # if have signed-off clause in description, # then make it the author $_ = $SIGN[0]; if (defined($_) && /^Signed-off-by: (.+) <(.+)>/) { $ENV{'GIT_AUTHOR_NAME'} = $1; $ENV{'GIT_AUTHOR_EMAIL'} = $2; } $Text::Wrap::columns = 75; $DESCRIPTION = Text::Wrap::fill('', '', @DESC); # Used to make sure we don't get duplicates my %SIGNOFFS; # Create the changeset file contents open CSET, ">changeset" or die "cannot open changeset file"; print CSET "$DESCRIPTION\n"; print CSET "\n"; print CSET "SGI-PV: $PVNUMBER\n"; print CSET "SGI-Modid: $MODID\n"; print CSET "\n"; foreach (@SIGN) { s/^#//; s/$/\n/; print CSET unless (defined($SIGNOFFS{$_})); $SIGNOFFS{$_} = 1; } # the mod author my $soff = "Signed-off-by: $MODSIGN\n"; print CSET $soff unless (defined($SIGNOFFS{$soff})); $SIGNOFFS{$soff} = 1; # the reviewers my $REV; my $REVSIGN; foreach $REV (sort(keys %REVIEWERS)) { $REVSIGN = $REVIEWERS{$REV}; $soff = "Signed-off-by: $REVSIGN\n"; print CSET $soff unless (defined($SIGNOFFS{$soff})); $SIGNOFFS{$soff} = 1; } # our own = $USER $soff = "Signed-off-by: $OWNSIGN\n"; print CSET $soff unless (defined($SIGNOFFS{$soff}) || ($REVIEWERS{$ENV{'USER'}})); $SIGNOFFS{$soff} = 1; close CSET; if (-s $QUILTPATCH) { print "We have the quilt patch previously imported to use\n"; } else { # Generate a -p1 patch from the mod, extracting unwanted pieces as we go open PATCH, ">$SUMMARY" or die "cannot open summary patch file\n"; open PRDIFF, "p_rdiff -PpuM ${MODID} |" or die "rdiff"; $/ = "\n===========================================================================\n"; my $skip = 0; while () { if ($skip == 1) { $skip = 0; } elsif (($KERNEL == 2.4) && ((m/^(Index: |)linux-2.6/) || (m/^(Index: |)Makefile-linux-2.6/))) { $skip = 1; } elsif (($KERNEL == 2.6) && ((m/^(Index: |)linux-2.4/) || (m/^(Index: |)Makefile-linux-2.4/))) { $skip = 1; } elsif (($KERNEL == 2.6) && (m,^(Index: |)quota/Makefile.*,)) { $skip = 1; } elsif (($KERNEL == 2.6) && (m/^(Index: |)xfs_refcache.[c|h]/)) { $skip = 1; } elsif ((m/^(Index: |)xfsidbg.c/) || (m/^(Index: |)Makefile/)) { $skip = 1; } elsif ((m,^(Index: |)dmapi/,) || (m/^(Index: |)xfs_dmapi.c/)) { $skip = 1; } elsif (m,^(Index: |)linux-2.[4|6]/xfs_ksyms.c,) { $skip = 1; } elsif (m,^(Index: |)quota/xfs_qm_ksyms.c,) { $skip = 1; } elsif ($TREEID eq 'dmapi') { s,^\-\-\- a/(\S+),--- a/fs/dmapi/$1,m; s,^\+\+\+ b/(\S+),+++ b/fs/dmapi/$1,m; print PATCH; } elsif ($TREEID eq 'xfs-kern') { s,^\-\-\- a/(\S+),--- a/fs/xfs/$1,m; s,^\+\+\+ b/(\S+),+++ b/fs/xfs/$1,m; print PATCH; } else { print PATCH; } } $/ = "\n"; close PRDIFF; # The patch is now complete close PATCH; print "Created patch: $SUMMARY\n"; `/usr/bin/diffstat "$SUMMARY"`; # put the patch into quilt chdir $GIT_TREE; if (! -d "patches") { mkdir "patches"; } print "Quilt importing the patch\n"; `quilt import $SUMMARY`; if ($? != 0) { print STDERR "WARNING: quilt import $SUMMARY failed\n"; exit 1; } } print "Quilt push the patch\n"; chdir $GIT_TREE; my $top = `quilt top`; chomp($top); if ($top eq $MODPATCH) { print "$MODPATCH is already applied\n"; } else { `quilt push $MODPATCH`; if ($? != 0) { print STDERR "WARNING: quilt patch wont apply cleanly, needs manual merge\n"; exit 1; } print "Push succeeded\n"; } # handle the new files my $fetal_files = ""; my $file = ""; my @words; open PATCH, "<$SUMMARY" or die "reading patch"; while () { if (m#^\+\+\+ b/#) { @words = split; $file = $words[1]; $file =~ s#^b/##; } elsif (m#^@@ -0,0 #) { if (!$fetal_files) { $fetal_files = $file; } else { $fetal_files = $fetal_files . " " . $file; } } } close PATCH; if ($fetal_files) { print "git add $fetal_files\n"; `git add $fetal_files`; } print "git-commit -a -F $CWD/changeset\n"; `git-commit -a -F "$CWD/changeset"`;