Michal Marek 2c93af
#!/usr/bin/perl
Michal Marek 2c93af
Michal Marek 2c93af
#############################################################################
Michal Marek 2c93af
# Copyright (c) 2015 Micro Focus
Michal Marek 2c93af
# All Rights Reserved.
Michal Marek 2c93af
#
Michal Marek 2c93af
# This program is free software; you can redistribute it and/or
Michal Marek 2c93af
# modify it under the terms of version 2 of the GNU General Public License as
Michal Marek 2c93af
# published by the Free Software Foundation.
Michal Marek 2c93af
#
Michal Marek 2c93af
# This program is distributed in the hope that it will be useful,
Michal Marek 2c93af
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Michal Marek 2c93af
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
Michal Marek 2c93af
# GNU General Public License for more details.
Michal Marek 2c93af
#
Michal Marek 2c93af
# You should have received a copy of the GNU General Public License
Michal Marek 2c93af
# along with this program; if not, contact Novell, Inc.
Michal Marek 2c93af
#
Michal Marek 2c93af
# To contact Novell about this file by physical or electronic mail,
Michal Marek 2c93af
# you may find current contact information at www.novell.com
Michal Marek 2c93af
#############################################################################
Michal Marek 2c93af
Michal Marek 2c93af
# Check that the a patch is in the format produced by scripts/refresh_patch.sh
Michal Marek 2c93af
Michal Marek 2c93af
use strict;
Michal Marek 2c93af
use warnings;
Michal Marek 2c93af
Michal Marek 2c93af
my $errors = 0;
Michal Marek 7e1d77
my $git_renames = 0;
Michal Marek 2c93af
my %reported;
Michal Marek 2c93af
our $file;
Michal Marek 2c93af
Michal Marek 2c93af
sub err {
Michal Marek 2c93af
	return if ($reported{"$file:$_[0]"}++);
Michal Marek 2c93af
	print STDERR "$file:$.: error: @_\n";
Michal Marek 2c93af
	$errors = 1;
Michal Marek 2c93af
}
Michal Marek 2c93af
Michal Marek 2c93af
sub check_filename {
Michal Marek 2c93af
	my $filename = shift;
Michal Marek 2c93af
Michal Marek 2c93af
	if ($filename !~ m:^(/dev/null\b|[ab]/):) {
Michal Marek 2c93af
		err("Patch not in -p ab format");
Michal Marek 2c93af
	}
Michal Marek 2c93af
	if ($filename =~ /\s\S/) {
Michal Marek 2c93af
		err("Timestamp after filename");
Michal Marek 2c93af
	}
Michal Marek 6c50fb
	if ($filename =~ /\/\//) {
Michal Marek 6c50fb
		err("Double slash in filename");
Michal Marek 6c50fb
	}
Michal Marek 2c93af
}
Michal Marek 2c93af
Michal Marek 2c93af
sub do_patch {
Michal Marek 2c93af
	my $fh = shift;
Michal Suchanek b3a11c
	my $fn = shift;
Michal Marek 2e07c1
	my ($in_payload, $in_hunk, $maybe_eof, $last_noncontext);
Michal Suchanek b3a11c
	my $xen_prefix = "patches.xen/";
Michal Suchanek b3a11c
	my $is_xen = $xen_prefix eq substr($fn,0,length($xen_prefix));
Michal Marek 2c93af
Michal Marek 2e07c1
	my @lines = <$fh>;
Michal Marek 2e07c1
	chomp(@lines);
Michal Marek 7e1d77
	for (my $i = 1; $i < scalar(@lines); $i++) {
Michal Marek 2e07c1
		my $cur = $lines[$i];
Michal Marek 2e07c1
		$. = $i + 1;
Michal Marek 7e1d77
		if ($cur =~ /^similarity index \d+%/ &&
Michal Marek 7e1d77
					$lines[$i-1] =~ /^diff --git/) {
Michal Marek 7e1d77
			$in_payload = 1;
Michal Marek 7e1d77
			$in_hunk = 0;
Michal Marek 7e1d77
			$maybe_eof = 0;
Michal Marek 7e1d77
			err("git diff -M patches fail with sequences-patch.sh --fast");
Michal Marek 7e1d77
			$git_renames = 1;
Michal Marek 7e1d77
		}
Michal Marek 7e1d77
		if ($cur =~ /^\+\+\+ / && $lines[$i-1] =~ /^--- /) {
Michal Marek 2e07c1
			$in_payload = 1;
Michal Marek 2e07c1
			$in_hunk = 0;
Michal Marek 2e07c1
			$maybe_eof = 0;
Michal Marek 2e07c1
			(my $new = $cur) =~ s/^\+\+\+ //;
Michal Marek 2e07c1
			(my $old = $lines[$i-1]) =~ s/^--- //;
Michal Suchanek b3a11c
			if (!$is_xen) { check_filename($new); }
Michal Suchanek b3a11c
			if (!$is_xen) { check_filename($old); }
Michal Suchanek b3a11c
			if (!$is_xen && $i > 2 && $lines[$i-2] =~ /^={20}/ &&
Michal Marek 2e07c1
						$lines[$i-3] =~ /^Index: /) {
Michal Marek 2e07c1
				err("Superfluous Index: line in patch");
Michal Marek 2e07c1
			}
Michal Marek 2e07c1
			next;
Michal Marek 2c93af
		}
Michal Marek 2e07c1
		next unless $in_payload;
Michal Marek 2e07c1
		if ($cur =~ /^(diff |Index: |--- |\\ No newline at end of file)/) {
Michal Marek 2e07c1
			$in_hunk = 0;
Michal Marek 2e07c1
			$maybe_eof = 0;
Michal Marek 2e07c1
			next;
Michal Marek 2e07c1
		} elsif ($cur =~ /^@@ /) {
Michal Marek 2e07c1
			$in_hunk = 1;
Michal Marek 2e07c1
			$last_noncontext = $i;
Michal Marek 2e07c1
			$maybe_eof = 0;
Michal Marek 2e07c1
			next;
Michal Marek 2e07c1
		}
Michal Marek 2e07c1
		next unless $in_hunk;
Michal Marek 2e07c1
		# "-- " can be used as signature delimiter and is sometimes
Michal Marek 2e07c1
		# written as "--"
Michal Marek 2e07c1
		if ($cur =~ /^-- ?$/) {
Michal Marek 2e07c1
			$maybe_eof = 1;
Michal Marek 2e07c1
			next;
Michal Marek 2e07c1
		}
Michal Marek 2e07c1
		if ($cur =~ /^[-+]/) {
Michal Marek 2e07c1
			$last_noncontext = $i;
Michal Marek 2e07c1
			next;
Michal Marek 2e07c1
		}
Michal Marek 2e07c1
		# Blank lines seem to be OK for git am
Michal Marek 2e07c1
		if ($cur =~ /^$|^ /) {
Michal Marek 2e07c1
			next;
Michal Marek 2e07c1
		}
Michal Marek 2e07c1
		# Try to ignore junk at the end of patch files
Michal Marek 2e07c1
		if ($i - $last_noncontext <= 3 && !$maybe_eof) {
Michal Marek 2e07c1
			err("Malformed patch (missing leading space in context line?)");
Michal Marek 2c93af
		}
Michal Marek 2c93af
	}
Michal Marek 2c93af
}
Michal Marek 2c93af
Michal Marek 2c93af
if (!@ARGV) {
Michal Marek 2c93af
	die "Usage: $0 <patch>...\n";
Michal Marek 2c93af
}
Michal Marek 2c93af
if ($ARGV[0] eq "--stdin") {
Michal Marek 2c93af
	shift;
Michal Marek 2c93af
	$file = "<stdin>";
Michal Marek 2c93af
	if (scalar(@ARGV)) {
Michal Marek 2c93af
		$file = $ARGV[0];
Michal Marek 2c93af
	}
Michal Marek 2c93af
	open(my $fh, '-');
Michal Suchanek b3a11c
	do_patch($fh, $file);
Michal Marek 2c93af
	close($fh);
Michal Marek 2c93af
} else {
Michal Marek 2c93af
	for $file (@ARGV) {
Michal Marek 2c93af
		open(my $fh, '<', $file) or die "$file: $!\n";
Michal Suchanek b3a11c
		do_patch($fh, $file);
Michal Marek 2c93af
		close($fh);
Michal Marek 2c93af
	}
Michal Marek 2c93af
}
Michal Marek 2c93af
Michal Marek 2c93af
if ($errors) {
Michal Marek 2c93af
	printf STDERR ("Please refresh the patch%s using scripts/refresh_patch.sh\n", (scalar(@ARGV) > 1 ? "es" : ""));
Michal Marek 7e1d77
	if ($git_renames) {
Michal Marek 7e1d77
		print STDERR "Use --no-renames when generating patches from git\n";
Michal Marek 7e1d77
	}
Michal Marek 2c93af
	exit(1);
Michal Marek 2c93af
}
Michal Marek 2c93af
exit(0);