#!/usr/bin/perl -w
use strict;
use File::Basename qq(basename);
use File::Copy qq(move);
my $tmpdir = $ENV{TMPDIR} || "/tmp";
die "Has to be run from the kernel-source GIT dir" if (! -d ".git");
if (scalar @ARGV < 2) {
print "Usage: $0 patch ids_file [nonzero_to_force_removal]\n";
exit 1;
}
open(SERIES, "+<series.conf") || die "cannot open series.conf";
my $series;
my $series_changed = 0;
{
local $/;
$series = <SERIES>;
}
my $patch = $ARGV[0];
my $idsfile = $ARGV[1];
my $force_removal = $ARGV[2] || 0;
my $destdir = "patches.kernel.org/";
my $dest = $destdir . basename $patch;
mkdir $destdir if (! -d $destdir);
if (-f $patch && ! -f $dest) {
move($patch, $dest) || die "cannot move $patch to $dest";
print "Moved $patch to $dest\n";
system("git add $dest");
print "Added $dest to GIT\n";
unless ($series =~ s/(latest standard kernel patches(?:\n[^\n]+)+\n)\n/$1\t$dest\n\n/) {
die "cannot find a place in series.conf to add the patch";
}
$series_changed = 1;
}
open(IDS, "<$idsfile") || die "cannot open $idsfile";
my $regexp = join "|", map { chomp; $_ } <IDS>;
close IDS;
my @references = ();
my %files;
if ($regexp eq "") {
print STDERR "empty regexp computed? Skipping patches removal...\n";
} else {
open(GIT, "git grep -E '$regexp' patches.*|") ||
die "cannot execute git";
my $tags = qr/(?:Git-[Cc]ommit: |Patch-[Mm]ainline: |From )([0-9a-f]{40})/;
while (<GIT>) {
chomp;
next if (/patches\.kernel\.org\/patch-[0-9]/);
/^([^:]+):($tags)?/;
my $file = $1;
# file may be deleted already
if (defined $2 && -f $file) {
open(PATCH, "<$file") || die "cannot open $file";
my %shas = ();
my @refs = ();
while (my $line = <PATCH>) {
chomp $line;
$shas{$1} = 1 if ($line =~ /^$tags/);
if ($line =~ /^References: (.*)$/) {
push @refs, (split /[\s,]+/, $1);
}
}
close PATCH;
if ($force_removal || scalar(keys %shas) == 1) {
push @references, @refs;
system("git rm $file");
$series =~ s/
(?:
# empty or non-comment line
(^(?:$|[ \t]*[^ \t#].*)\n)
# comment to be deleted
[ \t]*\#.*\n
)?
# file to be deleted
[ \t]+\Q$file\E[ \t]*\n
/$1 || ""/mex;
$series_changed = 1;
}
}
$files{$file} = 1;
}
close GIT;
}
if ($series_changed) {
seek(SERIES, 0, 0) || die "cannot seek series.conf";
truncate(SERIES, 0) || die "cannot truncate series.conf";
print SERIES $series;
}
close SERIES;
sub output_refs($@) {
my ($fh, @refs) = @_;
my %uniq = map {
s/fate/FATE/i;
s/bnc/bnc/i;
$_, 1
} @refs;
print $fh "References: ", join(' ', sort keys %uniq), "\n";
}
if (scalar @references) { REFS: {
unless (-f $dest) {
print STDERR "missed references:\n";
output_refs(\*STDERR, @references);
last REFS;
}
open(DEST, "<$dest") || die "cannot open $dest for reading";
my @dest = <DEST>;
close DEST;
open(DEST, ">$dest") || die "cannot open $dest for writing";
my $had_git_commit = 0;
foreach my $line (@dest) {
if (!$had_git_commit && $line =~ /^Git-commit: /) {
output_refs(\*DEST, @references);
$had_git_commit = 1;
} elsif ($line =~ /^References: (.*)$/) {
chomp $1;
push @references, (split /[\s,]+/, $1);
next;
}
print DEST $line;
}
undef @dest;
close DEST;
}}
foreach my $file (keys %files) {
if (-e $file) {
system("git grep -E '$regexp' $file");
}
}
0;