Jiri Slaby 5225f4
#!/usr/bin/perl -w
Jiri Slaby 5225f4
use strict;
Jiri Slaby 1dc9b0
use File::Basename qq(basename);
Jiri Slaby 1dc9b0
use Git;
Jiri Slaby 1dc9b0
use Storable qw(store);
Jiri Slaby 1dc9b0
use Term::ANSIColor qw(colored);
Jiri Slaby 5225f4
Takashi Iwai 278755
if (@ARGV < 2) {
Jiri Slaby 766976
	print "Usage: $0 suse_machine|-d stable_version\n";
Jiri Slaby 5225f4
	exit 1;
Jiri Slaby 5225f4
}
Jiri Slaby 5225f4
Takashi Iwai 278755
my $machine = shift;
Jiri Slaby 766976
my $dump_only = $machine eq '-d';
Takashi Iwai 278755
my $stable_ver = shift;
Jiri Slaby f2c6ff
my $old_version;
Jiri Slaby f2c6ff
my $new_version;
Jiri Slaby 193862
my $bsc;
Jiri Slaby 193862
Jiri Slaby 193862
my %bsc_map = (
Jiri Slaby dd4e55
	'other' => '1012628',
Jiri Slaby dd4e55
);
Jiri Slaby dd4e55
Jiri Slaby e23e1f
if ($stable_ver =~ /^v?(([3-9]\.[0-9]+)\.([0-9]+))$/) {
Jiri Slaby f2c6ff
	$new_version = $1;
Jiri Slaby f2c6ff
	$old_version = $2;
Jiri Slaby 193862
	$bsc = $bsc_map{$old_version};
Jiri Slaby 1dc9b0
	if ($3 ne 1) {
Jiri Slaby f2c6ff
		$old_version .= '.' . ($3 - 1);
Jiri Slaby 5225f4
	}
Jiri Slaby f2c6ff
} else {
Jiri Slaby f2c6ff
	die "cannot understand stable version $stable_ver";
Jiri Slaby 5225f4
}
Jiri Slaby 5225f4
Jiri Slaby 193862
if (!defined $bsc) {
Jiri Slaby 1dc9b0
	print colored("Kernel version not found in the map, assuming Tumbleweed\n", 'red');
Jiri Slaby 193862
	$bsc = $bsc_map{'other'};
Jiri Slaby dd4e55
}
Jiri Slaby dd4e55
Jiri Slaby 1dc9b0
my $patchpar = '/dev/shm';
Jiri Slaby 1dc9b0
my $patchdir = "patches-$new_version";
Jiri Slaby 1dc9b0
my $patchpath = "$patchpar/$patchdir";
Jiri Slaby 1dc9b0
my $idsfile = "$patchpath/ids";
Jiri Slaby 766976
if (!$dump_only && !mkdir $patchpath) {
Jiri Slaby 1dc9b0
	die "$patchpath already exists";
Jiri Slaby 1dc9b0
}
Jiri Slaby 5225f4
Jiri Slaby 1dc9b0
my $range = "v$old_version..v$new_version";
Jiri Slaby 1dc9b0
my $repo = Git->repository();
Jiri Slaby 1dc9b0
my @revs = $repo->command('rev-list', '--reverse', $range);
Jiri Slaby 1dc9b0
my %ids;
Jiri Slaby ecfeb0
my $digits = length scalar @revs;
Jiri Slaby 1dc9b0
my $counter = 1;
Jiri Slaby 1dc9b0
my @to_delete;
Jiri Slaby 1dc9b0
my $sha_re = qr/[0-9a-f]{40}/;
Jiri Slaby 1dc9b0
Jiri Slaby ecfeb0
$digits = 3 if ($digits < 3);
Jiri Slaby ecfeb0
Jiri Slaby 193862
print "References: bsc#$bsc $new_version\n" if ($dump_only);
Jiri Slaby 766976
Jiri Slaby 1dc9b0
foreach my $rev (@revs) {
Jiri Slaby 1dc9b0
	my ($filename, @commit_log) = $repo->command('show', '--no-patch',
Jiri Slaby 1dc9b0
		'--format=%f%n%B', $rev);
Jiri Slaby 1dc9b0
Jiri Slaby 1dc9b0
	my $cont = 0;
Jiri Slaby 1dc9b0
	my @shas;
Jiri Slaby 1dc9b0
	my @unmatched_shas;
Jiri Slaby 1dc9b0
Jiri Slaby 1dc9b0
	foreach (@commit_log) {
Jiri Slaby 1dc9b0
		if ($cont) {
Jiri Slaby 1dc9b0
			if (/^\s+($sha_re)\s*[\])]$/) {
Jiri Slaby 1dc9b0
				push @shas, $1;
Jiri Slaby 1dc9b0
				$cont = 0;
Jiri Slaby 1dc9b0
				next;
Jiri Slaby 1dc9b0
			}
Jiri Slaby 1dc9b0
		}
Jiri Slaby dd41f2
		if (/^[Cc]ommit ($sha_re) upstream\.?$/ ||
Jiri Slaby 1dc9b0
			/^[\[(]\s*[Uu]pstream commit ($sha_re)\s*[\])]$/ ||
Jiri Slaby 1dc9b0
			/^[uU]pstream commit ($sha_re)\.$/ ||
Jiri Slaby 4fec57
			/^This is a backport of ($sha_re)$/) {
Jiri Slaby 1dc9b0
			push @shas, $1;
Jiri Slaby 4fec57
		} elsif (/^\(cherry picked from commit ($sha_re)\)$/) {
Jiri Slaby 4fec57
			# if this is not the first SHA, it's likely DRM crap
Jiri Slaby 4fec57
			push(@shas, $1) if (!scalar @shas);
Jiri Slaby 1dc9b0
		} elsif (/^[\[(]\s*[Uu]pstream commits ($sha_re)\s+and\s*$/) {
Jiri Slaby 1dc9b0
			push @shas, $1;
Jiri Slaby 1dc9b0
			$cont = 1;
Jiri Slaby 1dc9b0
		} elsif (/^(Fixes:|This reverts commit) $sha_re(?: \(".*)?\.?$/ ||
Jiri Slaby 1dc9b0
			/^Link: .*lkml/) {
Jiri Slaby 1dc9b0
			# ignore
Jiri Slaby 1dc9b0
		} elsif (/\b$sha_re\b/) {
Jiri Slaby 1dc9b0
			push @unmatched_shas, $_;
Jiri Slaby 2f932c
		}
Jiri Slaby 2f932c
	}
Jiri Slaby 5225f4
Jiri Slaby 766976
	if ($dump_only) {
Jiri Slaby 766976
		print "$rev";
Jiri Slaby 766976
		if (scalar @shas) {
Jiri Slaby 766976
			print "=", join ' ', @shas;
Jiri Slaby 766976
		} else {
Jiri Slaby 766976
			print ' STABLE-ONLY patch: "', $commit_log[0], '"';
Jiri Slaby 766976
		}
Jiri Slaby 766976
		print "\n";
Jiri Slaby 766976
		next;
Jiri Slaby 766976
	}
Jiri Slaby 766976
Jiri Slaby 1dc9b0
	# better than nothing
Jiri Slaby 1dc9b0
	if (!scalar @shas) {
Jiri Slaby 1dc9b0
		push @shas, $rev;
Jiri Slaby 1dc9b0
	}
Jiri Slaby 5225f4
Jiri Slaby 1dc9b0
	my @patch = $repo->command('format-patch', '--stdout',
Jiri Slaby 1dc9b0
		'--signoff', '--no-renames',
Jiri Slaby 1dc9b0
		'-1', $rev,
Jiri Slaby 193862
		'--add-header', "References: bsc#$bsc",
Jiri Slaby 1dc9b0
		'--add-header', "Patch-mainline: $new_version",
Jiri Slaby 1dc9b0
		(map { ('--add-header', "Git-commit: $_") } @shas));
Jiri Slaby 1dc9b0
Jiri Slaby 1dc9b0
	# drop From
Jiri Slaby 1dc9b0
	shift(@patch) =~ /^From/ or die "From line is not the first one?";
Jiri Slaby 1dc9b0
Jiri Slaby ecfeb0
	my $newname = sprintf("${new_version}-%0${digits}d-%s", $counter,
Jiri Slaby ecfeb0
		$filename);
Jiri Slaby 1dc9b0
	# 57 is what git-format-patch uses
Jiri Slaby 1dc9b0
	$newname =~ s/^(.{1,57}).*$/$1.patch/;
Jiri Slaby 1dc9b0
	my $newpath = "$patchpath/$newname";
Jiri Slaby 1dc9b0
Jiri Slaby 1dc9b0
	open(PATCH, ">$newpath") or die "cannot output to $newpath";
Jiri Slaby 1dc9b0
	print PATCH join "\n", @patch;
Jiri Slaby 1dc9b0
	print PATCH "\n";
Jiri Slaby 1dc9b0
	close PATCH;
Jiri Slaby 1dc9b0
Jiri Slaby 1dc9b0
	$ids{$newname} = [ @shas ];
Jiri Slaby 1dc9b0
Jiri Slaby 1dc9b0
	$rev =~ /.{12}/;
Jiri Slaby 1dc9b0
	print colored($&, "yellow"), " -> $newname\n";
Jiri Slaby 1dc9b0
	foreach (@shas) {
Jiri Slaby 1dc9b0
		/.{12}/;
Jiri Slaby 1dc9b0
		print "\tUpstream SHA: ", colored("$&\n", "yellow");
Jiri Slaby 1dc9b0
	}
Jiri Slaby 1dc9b0
	foreach (@unmatched_shas) {
Jiri Slaby 1dc9b0
		print colored("\tUNMATCHED SHA:", 'bold red'), " $_\n";
Jiri Slaby 1dc9b0
	}
Jiri Slaby 5225f4
Jiri Slaby 1dc9b0
	push @to_delete, $newpath;
Jiri Slaby 1dc9b0
	$counter++;
Jiri Slaby 5225f4
}
Jiri Slaby 5225f4
Jiri Slaby 766976
exit 0 if ($dump_only);
Jiri Slaby 766976
Jiri Slaby 1dc9b0
store(\%ids, $idsfile) or die "cannot write $idsfile";
Jiri Slaby 1dc9b0
push @to_delete, $idsfile;
Jiri Slaby 5225f4
Jiri Slaby 2e223f
if ($machine ne 'localhost') {
Jiri Slaby 2e223f
	system("tar -cC $patchpar $patchdir|ssh -C $machine -o StrictHostKeyChecking=no 'tar -xC $patchpar'") == 0 ||
Jiri Slaby 2e223f
		die "ssh didn't start";
Jiri Slaby 2e223f
	unlink(@to_delete) or print STDERR "cannot delete some temp files\n";
Jiri Slaby 2e223f
	rmdir("$patchpath") or print STDERR "cannot remove $patchpath\n";
Jiri Slaby 2e223f
}
Jiri Slaby 5225f4
Jiri Slaby 2e223f
print "Written patches and ids to $machine:$patchpath\n";
Jiri Slaby 5225f4
Jiri Slaby 5225f4
0;