238 lines
6.3 KiB
Perl
Executable File
238 lines
6.3 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# SPDX-FileCopyrightText: 2010-2011 Jan Engelhardt
|
|
#
|
|
# spec-beautifier - make .spec files shine again
|
|
#
|
|
use Getopt::Long;
|
|
use strict;
|
|
my $opt_diff_mode;
|
|
my $opt_replace_inline;
|
|
|
|
our $PSTOP = qr<(?=[\s/]|$)>;
|
|
our $IDNAME = qr<[A-Za-z_][A-Za-z_0-9]*>;
|
|
our $VSTOP = qr<(?![A-Za-z_0-9])>;
|
|
our $VRSTOP = qr<(?![A-Za-z_0-9\*])>;
|
|
|
|
sub help
|
|
{
|
|
print "Usage: $ARGV[0] [-d|-r]\n";
|
|
print " -d Generate diff-like output\n";
|
|
print " -r Replace file in line rather than printing to stdout\n";
|
|
exit(0);
|
|
}
|
|
|
|
sub process_generic
|
|
{
|
|
my($s) = shift @_;
|
|
|
|
if ($s->{sectype} eq "shell") {
|
|
# Undo crimes on shell vars
|
|
s<\$\{($IDNAME)\}$VSTOP> <\$$1>g;
|
|
|
|
# Shell variables to RPM macros
|
|
#s<\$RPM_SOURCE_DIR> <\%_sourcedir>g;
|
|
#s<\$RPM_BUILD_DIR> <\%_builddir>g;
|
|
s<\$RPM_OPT_FLAGS$VSTOP> <\%optflags>g;
|
|
s<\$RPM_ARCH$VSTOP> <\%_arch>g;
|
|
s<\$RPM_OS$VSTOP> <\%_os>g;
|
|
s<\$RPM_BUILD_ROOT$VSTOP> <\%buildroot>g;
|
|
s<\$RPM_DOC_DIR$VSTOP> <\%_docdir>g;
|
|
s<\$RPM_PACKAGE_NAME$VSTOP> <\%name>g;
|
|
s<\$RPM_PACKAGE_VERSION$VSTOP> <\%version>g;
|
|
s<\$RPM_PACKAGE_RELEASE$VSTOP> <\%release>g;
|
|
}
|
|
|
|
# Hardcoded paths to macros
|
|
s</etc/init.d$PSTOP> <\%_initddir>g;
|
|
s</etc$PSTOP> <\%_sysconfdir>g;
|
|
s</usr/bin$PSTOP> <\%_bindir>g;
|
|
s</usr/sbin$PSTOP> <\%_sbindir>g;
|
|
s</usr/libexec$PSTOP> <\%_libexecdir>g;
|
|
s</usr/include$PSTOP> <\%_includedir>g;
|
|
s</usr/share/man$PSTOP> <\%_mandir>g;
|
|
s</usr/share/info$PSTOP> <\%_infodir>g;
|
|
s</usr/share$PSTOP> <\%_datadir>g;
|
|
if (m</usr/lib$PSTOP>) {
|
|
print STDERR "$s->{pos}: Seen \"/usr/lib\". Consider replacing with \%_libdir or \%_libexecdir as appropriate.\n";
|
|
}
|
|
if (m</usr/lib64$PSTOP>) {
|
|
print STDERR "$s->{pos}: Seen \"/usr/lib64\". Consider fixing it.\n";
|
|
}
|
|
if (m{(?:^|\s)/lib$PSTOP}) {
|
|
print STDERR "$s->{pos}: Seen \"/lib\". Consider replacing with \%_lib as appropriate.\n";
|
|
}
|
|
if (m{(?:^|\s)/lib64$PSTOP}) {
|
|
print STDERR "$s->{pos}: Seen \"/lib64\". Consider fixing it.\n";
|
|
}
|
|
|
|
# Temporarily add {} to reduce following regexes
|
|
s<\%($IDNAME)> <\%{$1}>g;
|
|
|
|
# Upgrade macros to newer forms
|
|
if (m<\%\{_initrddir\}>g) {
|
|
print STDERR "$s->{pos}: Try not to use \%_initrddir (this was a typo introduced in rpm) anymore, use \%_initddir. NOTE: SLES11 does not know the new variable yet.\n";
|
|
}
|
|
s<\%\{_usr\}> <\%{_prefix}>g;
|
|
s<\%\{_var\}> <\%{_localstatedir}>g;
|
|
s<\%\{_prefix\}/+\%\{_lib\}> <\%{_libdir}>g;
|
|
|
|
# Replace macros by normal forms
|
|
my %util = ("id_u" => "id -u", "ln_s" => "ln -s",
|
|
"lzma" => "xz --format-lzma", "mkdir_p" => "mkdir -p",
|
|
"awk" => "gawk", "cc" => "gcc", "cpp" => "gcc -E",
|
|
"cxx" => "g++", "remsh" => "rsh");
|
|
foreach my $re (keys %util) {
|
|
s<\%\{__$re\}><$util{$re}>g;
|
|
}
|
|
|
|
foreach my $re (qw(aclocal ar as autoconf autoheader automake bzip2
|
|
cat chgrp chmod chown cp cpio file gpg grep gzip id install ld
|
|
libtoolize make mkdir mv nm objcopy objdump patch perl python
|
|
ranlib restorecon rm rsh sed semodule ssh strip tar unzip xz))
|
|
{
|
|
s<\%\{__$re\}><$re>g;
|
|
}
|
|
|
|
# Removal of .la files
|
|
foreach my $re (
|
|
qr<find \%buildroot -type f -name "\*\.la" -exec rm -f?vf? \{\} \+$>,
|
|
qr<find \%buildroot -type f -name '\*\.la' -exec rm -f?vf? \{\} \+$>,
|
|
qr<find \%buildroot -type f -name "\*\.la" -print0 \| xargs -0 rm -f?vf?$>,
|
|
qr<find \%buildroot -type f -name '\*\.la' -print0 \| xargs -0 rm -f?vf?$>)
|
|
{
|
|
my $tmp = $_;
|
|
$tmp =~ s<\s+>< >gs;
|
|
s<$re><find \%buildroot -type f -name "*.la" -delete -print>;
|
|
}
|
|
foreach (qr<find \%buildroot -type f -name "\*\.la" -exec rm -f \{\} \+$>,
|
|
qr<find \%buildroot -type f -name '\*\.la' -exec rm -f \{\} \+$>,
|
|
qr<find \%buildroot -type f -name "\*\.la" -print0 \| xargs -0 rm -fv$>,
|
|
qr<find \%buildroot -type f -name '\*\.la' -print0 \| xargs -0 rm -fv$>)
|
|
{
|
|
s<$_><find \%buildroot -type f -name "*.la" -delete -print>;
|
|
}
|
|
|
|
# Guard BS variables
|
|
foreach my $re (qw(centos debian fedora mandrive meego rhel
|
|
sles suse ubuntu))
|
|
{
|
|
s<\%\{${re}_version\}><0\%\{?${re}_version}>g;
|
|
}
|
|
|
|
# Undo crimes on RPM macros
|
|
s<\%\{($IDNAME)\}$VRSTOP> <\%$1>g;
|
|
|
|
# More Build System freedom
|
|
s<\%\{\?jobs\s*:\s*-j\s*\%jobs\}><\%{?_smp_mflags}>g;
|
|
}
|
|
|
|
sub process_package
|
|
{
|
|
s<^\s*(\S+)\s*:> <$1:>g;
|
|
s<^([A-Za-z])(\S+):> <uc($1).lc($2).":">eg;
|
|
s<^Prereq:> <PreReq:>g;
|
|
s<^Buildrequires:> <BuildRequires:>g;
|
|
s<^Buildarch:> <BuildArch:>g;
|
|
s<^Url:> <URL:>g;
|
|
|
|
if (m<^Buildroot:(\s*).*>) {
|
|
return 0;
|
|
}
|
|
if (s<^Packager:.*> <>i) {
|
|
print STDERR "You should not use the Packager tag. These are set by the Build Service.\n";
|
|
return 0;
|
|
}
|
|
if (s<^Distribution:.*> <>i) {
|
|
print STDERR "You should not use the Distribution tag. These are set by the Build Service/prjconf.\n";
|
|
return 0;
|
|
}
|
|
if (s<^Vendor:.*> <>i) {
|
|
print STDERR "You should not use the Vendor tag. These are set by the Build Service/prjconf.\n";
|
|
return 0;
|
|
}
|
|
if (m<^\s*\%define\s*(name|version|release)\b.*>i) {
|
|
print STDERR "Defining \%$1 is pointless. Just use the actual \"$1:\" tag.\n";
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub process_master
|
|
{
|
|
local *FH = shift @_;
|
|
my $s = shift @_;
|
|
my $repl = [];
|
|
my $old;
|
|
|
|
$s->{line} = 0;
|
|
$s->{sectype} = "package";
|
|
while (<FH>) {
|
|
++$s->{line};
|
|
$s->{pos} = $s->{file}.":".$s->{line};
|
|
$old = $_;
|
|
if (m<^\%(package|description|files)\b>) {
|
|
$s->{sectype} = $s->{section} = $1;
|
|
} elsif (m<\%(prep|build|install|check|clean|pre|post|preun|postun)>) {
|
|
$s->{sectype} = "shell";
|
|
$s->{section} = $1;
|
|
}
|
|
&process_generic($s);
|
|
if ($s->{sectype} eq "package") {
|
|
if (!&process_package()) {
|
|
next;
|
|
}
|
|
}
|
|
if ($opt_diff_mode) {
|
|
print (($old ne $_) ? "-$old+$_" : " $_");
|
|
} elsif ($opt_replace_inline) {
|
|
push(@$repl, $_);
|
|
} else {
|
|
print;
|
|
}
|
|
}
|
|
|
|
return $repl;
|
|
}
|
|
|
|
sub process_file
|
|
{
|
|
my $file = shift @_;
|
|
my $state = {"file" => $file};
|
|
local *FH;
|
|
|
|
if (!open(FH, "< $file")) {
|
|
print STDERR "Error opening for reading $file: $!\n";
|
|
return;
|
|
}
|
|
|
|
my $repl = &process_master(\*FH, $state);
|
|
close FH;
|
|
|
|
if (!$opt_diff_mode && $opt_replace_inline) {
|
|
if (!open(FH, "> $file")) {
|
|
print STDERR "Error opening $file for write: $!\n";
|
|
return;
|
|
}
|
|
print FH @$repl;
|
|
close FH;
|
|
}
|
|
}
|
|
|
|
sub main
|
|
{
|
|
&Getopt::Long::Configure(qw(bundling));
|
|
&GetOptions(
|
|
"d" => \$opt_diff_mode,
|
|
"r" => \$opt_replace_inline,
|
|
"h" => sub { &help(); },
|
|
);
|
|
if (scalar(@ARGV) == 0) {
|
|
@ARGV = ("-");
|
|
}
|
|
foreach (@ARGV) {
|
|
&process_file($_);
|
|
}
|
|
}
|
|
|
|
&main();
|