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