#!/usr/bin/perl -W use strict; # Usage: checkspec specfile1 specfile2 ... # This small script does some checks on spec files to avoid errors which i # make a lot like forgetting the %clean section # Currently it checks the following: # * %clean section # * no LC_MESSAGES in %files section # * correct buildroot # * no 'install ' but %{__install} # Feel free to add checks if you like my $DEBUG = 0; my %specproblems = (); sub debug { my $line = pop; if ($DEBUG) { print $line . "\n"; } } sub checkDocInAlphabeticalOrder { my $METHOD_NAME = "checkDocInAlphabeticalOrder - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); my @lines = split("\n", $filecontents); my $line; foreach $line (@lines) { #print STDERR "doc line? " . $line; if ($line =~ /^\%doc (.*)/) { my $filenamesString = $1; my @filenames = split(" ", $filenamesString); my @filenamesSorted = sort {uc($a) cmp uc($b)} @filenames; my $filenamesStringSorted = join(" ", @filenamesSorted); #print STDERR "orig doc line: " . $filenamesString . ",sorted: " . $filenamesStringSorted . "\n"; if (!($filenamesStringSorted eq $filenamesString)) { print STDERR $filename . " : doc line not sorted alphabetically, orig doc line: " . $filenamesString . ",sorted: " . $filenamesStringSorted . "\n"; $specproblems{$filename} = 1; } } } } sub checkChangelog { my $METHOD_NAME = "checkChangelog - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); if ($filecontents =~ /%changelog\n/) { debug($METHOD_NAME . "changelog line ok"); } else { print STDERR $filename . " : changelog section not ok\n"; $specproblems{$filename} = 1; } } sub checkCleanSection { my $METHOD_NAME = "checkCleanSection - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); if ($filecontents =~ /\%clean\n\%\{__rm\} \-rf \%\{buildroot\}/) { debug($METHOD_NAME . "clean section ok"); } else { print STDERR $filename . " : %clean section not ok\n"; $specproblems{$filename} = 1; } } sub checkRmRfBeforeInstall { my $METHOD_NAME = "checkRmRfBeforeInstall - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); if ($filecontents =~ /\%install\n\%\{__rm\} \-rf \%\{buildroot\}/) { debug($METHOD_NAME . "install section starts with rm rf, ok"); } else { print STDERR $filename . " : install section does not start with rm rf\n"; $specproblems{$filename} = 1; } } sub checkNoLcMessagesInFilesSection { my $METHOD_NAME = "checkNoLcMessagesInFilesSection - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); # get the %files part of the spec file $filecontents =~ s/.*\%files//gs; debug($METHOD_NAME . "files sections: \n##### START #####\n" . $filecontents . "##### END #####"); if (!($filecontents =~ /LC_MESSAGES/)) { debug($METHOD_NAME . "LC_MESSAGES in %files not found, ok"); } else { print STDERR $filename . " : contains LC_MESSAGES in %files section\n"; $specproblems{$filename} = 1; } } sub checkOnlyMacrosInFiles { my $METHOD_NAME = "checkOnlyMacrosInFiles - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); # get the %files part of the spec file $filecontents =~ s/.*\%files//gs; debug($METHOD_NAME . "files sections: \n##### START #####\n" . $filecontents . "##### END #####"); if (!($filecontents =~ /\n\//)) { debug($METHOD_NAME . "no line after %files which starts with a slash, ok"); } else { print STDERR $filename . " : contains lines which start with a slash in %files section\n"; $specproblems{$filename} = 1; } } sub checkMacros { my $METHOD_NAME = "checkMacros - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); if ($filecontents =~ /^[ \t]*install/gm) { print STDERR $filename . " : contains install, should be \%\{__install\}\n"; $specproblems{$filename} = 1; } else { debug($METHOD_NAME . "checkMacros ok"); } } sub checkBuildRoot { my $METHOD_NAME = "checkBuildRoot - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); if ($filecontents =~ /^BuildRoot:\s*\%\{\_tmppath\}\/\%\{name\}\-\%\{version\}\-\%\{release\}\-root$/gm) { debug($METHOD_NAME . "buildroot ok"); } else { print STDERR $filename . " : buildroot not ok\n"; $specproblems{$filename} = 1; } # BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root } sub checkLineLength { my $METHOD_NAME = "checkLineLength - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); my @lines = split("\n", $filecontents); my $line; foreach $line (@lines) { if (length($line) > 80) { if (!($line =~ /^Source[0-9]*:/) && !($line =~/^# Screenshot/) && !($line =~/^\%define/)) { print STDERR $filename . " : line too long, line: " . $line . "\n"; $specproblems{$filename} = 1; } } } } sub checkDefattrLines { # %defattr(-,root,root,0755) my $METHOD_NAME = "checkDefattrLines - "; my ($filename, $filecontents) = @_; debug($METHOD_NAME . "start, filename=" . $filename); my @lines = split("\n", $filecontents); my $line; my $lastlineWasFilesLine = 0; foreach $line (@lines) { debug($METHOD_NAME . "lastlineWasFilesLine=" . $lastlineWasFilesLine . ",line=" . $line); if ($line =~ /^\%files/) { $lastlineWasFilesLine = 1; next; } debug($METHOD_NAME . "lastlineWasFilesLine is now " . $lastlineWasFilesLine); if ($lastlineWasFilesLine) { if ($line =~ /^%defattr\(([0-9a-zA-Z -]*),([0-9a-zA-Z -]*),([0-9a-zA-Z -]*),([0-9a-zA-Z -]*)\)/) { if (!($line =~ /^%defattr\(([0-9a-zA-Z-]*), ([0-9a-zA-Z-]*), ([0-9a-zA-Z-]*), ([0-9a-zA-Z-]*)\)/)) { print STDERR $filename . " : spaces not ok in defattr, line= " . $line . "\n"; } $lastlineWasFilesLine = 0; next; } if ($line =~ /^%defattr\(([0-9a-zA-Z -]*),([0-9a-zA-Z -]*),([0-9a-zA-Z -]*)\)/) { print STDERR $filename . " : no chmod mode at end of defattr, line= " . $line . "\n"; $lastlineWasFilesLine = 0; next; } print STDERR $filename . " : no defattr line after files section\n"; $lastlineWasFilesLine = 0; } } } sub checkSpec { my $METHOD_NAME = "checkSpec - "; my $filename = pop; debug($METHOD_NAME . "start, filename is " . $filename); my $filecontents = ""; open(FILE, "<$filename") or die "could not open file " . $filename; while () { $filecontents = $filecontents . $_; } close FILE; debug("filecontents is: \n#### START ####\n" . $filecontents . "#### END ####"); checkCleanSection($filename, $filecontents); checkNoLcMessagesInFilesSection($filename, $filecontents); checkBuildRoot($filename, $filecontents); checkLineLength($filename, $filecontents); checkOnlyMacrosInFiles($filename, $filecontents); checkDefattrLines($filename, $filecontents); checkRmRfBeforeInstall($filename, $filecontents); checkMacros($filename, $filecontents); checkChangelog($filename, $filecontents); checkDocInAlphabeticalOrder($filename, $filecontents); } sub printJoeLine { my $line = ""; my $name; foreach $name (keys %specproblems) { chomp $name; $line = $line . " " . $name; } print STDERR "joe " . $line . "\n"; } my @filenames = @ARGV; my $fname; foreach $fname (sort @filenames) { # print $fname . "\n"; checkSpec $fname; } printJoeLine;