1
0
Stephan Kulow 2011-12-06 08:55:21 +00:00 committed by Git OBS Bridge
parent 74a0c34178
commit 0b56edb017
4 changed files with 338 additions and 115 deletions

View File

@ -0,0 +1,59 @@
#
# spec file for package obs-service-format_spec_file
#
# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
Name: obs-service-format_spec_file
Summary: An OBS source service: reformats a spec file to SUSE standard.
License: GPL-2.0+
Group: Development/Tools/Building
Version: 0.3
Release: 0
Source: format_spec_file
Source1: format_spec_file.service
Source2: prepare_spec
Requires: osc-source_validator
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildArch: noarch
%description
This is a source service for openSUSE Build Service.
This source service is formating the spec file to SUSE standard. The rational
behind is to make it easier to review spec files from unknown packagers.
This should be used in "trylocal" mode, so that osc is adapting the existing
spec file instead of creating a new one.
%prep
%setup -q -D -T 0 -n .
%build
%install
mkdir -p $RPM_BUILD_ROOT/usr/lib/obs/service/format_spec_file.files
install -m 0755 %{SOURCE0} $RPM_BUILD_ROOT/usr/lib/obs/service
install -m 0644 %{SOURCE1} $RPM_BUILD_ROOT/usr/lib/obs/service
install -m 0755 %{SOURCE2} $RPM_BUILD_ROOT/usr/lib/obs/service/format_spec_file.files
%files
%defattr(-,root,root)
%dir /usr/lib/obs
/usr/lib/obs/service
%changelog

View File

@ -1,3 +1,8 @@
-------------------------------------------------------------------
Tue Dec 6 08:50:41 UTC 2011 - coolo@suse.com
- update from https://github.com/openSUSE/obs-service-format_spec_file
-------------------------------------------------------------------
Thu Dec 1 14:10:52 UTC 2011 - adrian@suse.de

View File

@ -16,13 +16,12 @@
#
Name: obs-service-format_spec_file
License: GPL v2 or later
Group: Development/Tools/Building
Summary: An OBS source service: reformats a spec file to SUSE standard.
Version: 0.2
Release: 11
License: GPL-2.0+
Group: Development/Tools/Building
Version: 0.3
Release: 0
Source: format_spec_file
Source1: format_spec_file.service
Source2: prepare_spec

View File

@ -15,21 +15,20 @@ use strict;
my @oldspec = ();
my @newspec = ();
my $base_package = "";
my $neededforbuild = "";
my $icecreamforbuild = "";
my $norootforbuild = 0;
my @copyrights = ();
my $needsrootforbuild = 0;
my $needsbinariesforbuild = 0;
my $nodebuginfo = 0;
my %multiline_macros = ();
my $vim_modeline;
my $nosrc_result = 0;
my $current_section = "header";
my $had_debug_package = 0;
my %pkg_version = ();
my %pkg_release = ();
my %please_replace = ();
my %replace_hash = ();
my $main_license;
my %seen_licenses = ();
my $main_group;
my %seen_groups = ();
my $build_root = $ENV{'BUILD_ROOT'};
my $disabled_packs;
my $ifhandler;
@ -51,6 +50,8 @@ my @global_tags_list =
'ExcludeArch',
'ExclusiveArch',
'Freshens',
'Group',
'Name',
'NoPatch',
'NoSource',
'Obsoletes',
@ -62,6 +63,7 @@ my @global_tags_list =
'Requires',
'Source\d*',
'Suggests',
'Summary',
'Supplements',
'Url',
);
@ -93,10 +95,19 @@ sub capitalize_case($)
return $tag;
}
sub compare_arrays {
my ($first, $second) = @_;
return 0 unless @$first == @$second;
for (my $i = 0; $i < @$first; $i++) {
return 0 if $first->[$i] ne $second->[$i];
}
return 1;
}
sub maybe_add_empty_line()
{
push @oldspec, "XXXBLANKLINE"
if ($current_section ne "description" && $oldspec[-1] !~ /^\s*$/);
if ($current_section ne "description" && $oldspec[-1] !~ /^\s*$/ && $oldspec[-1] !~ /^[#%]/);
}
sub change_section($)
@ -109,6 +120,149 @@ sub change_section($)
warn "section changed to $current_section\n" if $debug;
}
sub replace_single_spdx($)
{
my ($l) = @_;
my %replace = (
"lgplv2.1only" =>"LGPL-2.1",
"lgplv2.1orlater" => "LGPL-2.1+",
"lgplv2.1+" => "LGPL-2.1+",
"lgplv2.1" => "LGPL-2.1",
"lgplv2.0+" => "LGPL-2.0+",
"lgplv2.0" => "LGPL-2.0",
"lgplv2+" => "LGPL-2.1+",
'lgplv3' => "LGPL-3.0",
'lgplv3+' => "LGPL-3.0+",
'gnulgplv2.1orlater' => "LGPL-2.1+",
'gnulgplv2.1' => "LGPL-2.1",
'lgplv2.0orlater' => 'LGPL-2.0+',
'lgplv2orlater' => 'LGPL-2.0+',
"lgplv3only" => "LGPL-3.0",
"lgplv3orlater" => "LGPL-3.0+",
"gpl" => "GPL-1.0",
"gpl+" => "GPL-1.0+",
"gplv2only" => "GPL-2.0",
"gplv2" => "GPL-2.0",
"gpl2" => "GPL-2.0",
"gplv2orlater" => "GPL-2.0+",
"gplv2.0orlater" => "GPL-2.0+",
"gplv2+" => "GPL-2.0+",
"gpl-2+" => "GPL-2.0+",
"gplv3only" => "GPL-3.0",
"gplv3orlater" => "GPL-3.0+",
"gplv3+" => "GPL-3.0+",
"gplv3" => "GPL-3.0",
"gpl-3+" => "GPL-3.0+",
"gnugplversion3" => "GPL-3.0",
"fdl1.1" => "GFDL-1.1",
"gfdlv1.1" => "GFDL-1.1",
'gnufreedocumentationlicense,version1.1(fdl1.1)' => "GFDL-1.1",
'gnufreedocumentationlicense,version1.1(gfdl1.1)' => "GFDL-1.1",
"fdl1.2" => "GFDL-1.2",
"gfdl1.2" => "GFDL-1.2",
"gfdlv1.2" => "GFDL-1.2",
'gnufreedocumentationlicense,version1.2(fdl1.2)' => "GFDL-1.2",
'gnufreedocumentationlicense,version1.2(gfdl1.2)' => "GFDL-1.2",
"fdl1.3" => "GFDL-1.3",
"bsd-2c" => "BSD-2-Clause",
"bsd3-clause" => "BSD-3-Clause",
"bsd3c" => "BSD-3-Clause",
"bsd3c(orsimilar)" => "BSD-3-Clause",
"bsd3-clause(orsimilar)" => "BSD-3-Clause",
"bsd4c" => "BSD-4-Clause",
"bsd4c(orsimilar)" => "BSD-4-Clause",
"x11/mit" => "MIT",
"X11mit" => "MIT",
"mitlicense(orsimilar)" => "MIT",
"asl2.0" => "Apache-2.0",
'apachelicense2.0' => "Apache-2.0",
'apachelicense' => "Apache-2.0",
'theapachesoftwarelicense' => "Apache-2.0",
"apachesoftwarelicense.." => "Apache-2.0",
'apachesoftware license..' => "Apache-2.0",
'aslv..' => "Apache-2.0",
'aslv2' => "Apache-2.0",
"artistic" => "Artistic-1.0",
"artistic2.0" => "Artistic-2.0",
"thephplicense,version3.01" => "PHP-3.01",
"phplicense" => "PHP-3.01",
"mplv1.0" => "MPL-1.0",
"mplv1.1" => "MPL-1.1",
"ibmpubliclicense.." => "IPL-1.0",
"ibmpl" => "IPL-1.0",
"eclipsepubliclicense" => "EPL-1.0",
"openldap2.8" => "OLDAP-2.8",
"zliblicense" => "Zlib"
);
my $tl = lc $l;
$tl =~ s, ,,g;
if (defined $replace{$tl}) {
$l = $replace{$tl};
} else {
my @m = grep(lc($_) eq lc($l), values(%replace));
if (@m) {
$l = $m[0];
} else {
print STDERR "unknown license '$l'\n";
}
}
return $l;
}
sub replace_spdx_or($)
{
my ($license) = @_;
# special case as or later is common in our spec files
$license =~ s, or later, orlater,g;
my @licenses = ();
for (split(/\s+or\s+/, $license)) {
push @licenses, replace_single_spdx($_);
}
return join(' or ', sort(@licenses));
}
sub replace_spdx_and($)
{
my ($license) = @_;
my @licenses = ();
for (split(/\s*and\s*/, $license)) {
push @licenses, replace_spdx_or($_);
}
return join(' and ', sort(@licenses));
}
sub replace_spdx($)
{
my ($license) = @_;
my @licenses = ();
for (split(/\s*;\s*/, $license)) {
push @licenses, replace_spdx_and($_);
}
return join(' ; ', sort(@licenses));
}
sub set_current_pkg {
my ( $arg ) = @_;
print "DEBUG: set_current_pkg receiving $arg\n" if $debug;
@ -148,15 +302,23 @@ sub read_and_parse_old_spec {
while (@readspec) {
$_ = shift @readspec;
if ( /^\s*$/ && $current_section ne "description") {
# stop preamble parsing on two blank lines
if ($print_comments eq "false" && $oldspec[0] && $oldspec[-1] eq "XXXBLANKLINE") {
$print_comments = "true";
push @oldspec, "XXXDOUBLELINE";
next;
}
push @oldspec, "XXXBLANKLINE";
next;
}
if ( /^#\s*norootforbuild\s*$/ ) {
$norootforbuild = 1;
next;
if ( /^# vim:/ ) {
$vim_modeline = $_;
next;
}
if ( /^#\s*needsrootforbuild\s*$/ ) {
$needsrootforbuild = 1;
next;
@ -165,6 +327,10 @@ sub read_and_parse_old_spec {
$needsbinariesforbuild = 1;
next;
}
if ( /^#\s*norootforbuild/ ) {
next;
}
if ( /^#\s*nodebuginfo\s*$/ ) {
$nodebuginfo = 1;
next;
@ -175,6 +341,7 @@ sub read_and_parse_old_spec {
next;
}
if ( /^#\s*Copyright\s*/ ) {
my $lastlineblank = 0;
for (;;)
{
# check if line is ONLY a standard copyright line, if so, ignore.
@ -182,22 +349,11 @@ sub read_and_parse_old_spec {
$c =~ s{\s*(\d+|copyrights?|\(c\)|suse|linux|products|gmbh|nuremberg|n..?rnberg|germany|\W+)\s*}{}gi;
push(@copyrights, $_) if length $c > 5;
last if length $readspec[0] < 10 || $readspec[0] =~ m{modifications and additions}i || $readspec[0] !~ /^[\#\s]/
|| grep { $readspec[0] =~ /^#\s*$_/ } ("norootforbuild","needsrootforbuild","needsbinariesforbuild","nodebuginfo","icecream","neededforbuild","usedforbuild","Commandline","MD5SUM","!BuildIgnore");
|| grep { $readspec[0] =~ /^#\s*$_/ } ("needsrootforbuild","needsbinariesforbuild","nodebuginfo","icecream","usedforbuild","Commandline","MD5SUM","!BuildIgnore");
$_ = shift @readspec;
}
next;
}
if ( /^#\s*neededforbuild/ ) {
$neededforbuild = $_;
$neededforbuild =~ s/^#\s*neededforbuild\s*//;
my (%aa) = ();
foreach my $x (split(' ',$neededforbuild)){
$aa{$x}=1;
}
$neededforbuild = join(' ',sort keys (%aa));
next;
}
# evil epoch removal
next if ( /^Epoch:/ );
$_ =~ s/%{?epoch}?[:-]//g;
@ -213,7 +369,9 @@ sub read_and_parse_old_spec {
# ignore line if it looks like a "usedforbuild" line, i.e.
# if it contains too many base packages
next if (grep {$aa{$_}} qw{gcc rpm glibc bash}) > 2;
push @oldspec, "BuildRequires: ".join(' ',sort keys(%aa));
for my $br (sort keys(%aa)) {
push @oldspec, "BuildRequires: $br";
}
next;
}
next if ( /^#\s*usedforbuild/ );
@ -229,6 +387,7 @@ sub read_and_parse_old_spec {
push @oldspec, $_;
next;
}
if ( /^#/ && $current_section ne "description") {
warn "$_ $current_section\n" if $debug;
if ( $print_comments eq "true" || $readspec[0] =~ /^%define/ || $readspec[0] =~ /^%if/) {
@ -236,6 +395,7 @@ sub read_and_parse_old_spec {
}
next;
}
if ( /^%debug_package/ ) {
# remove, we add this ourselves
next;
@ -245,9 +405,7 @@ sub read_and_parse_old_spec {
if ( /^%define\s*vendor\s/ || /^%define\s*distribution\s/ ) {
next;
}
if ( /^%define\s+(\w[\w\d]+).*\\$/ ) {
$multiline_macros{$1} = 1;
}
if ( /^\s*%if/ || /^\s*%\{/ || /^\s*%define/ || /^\s*%el/ || /^\s*%endif/ ) {
change_section("header") if ($current_section eq "description");
push @oldspec, $_;
@ -330,13 +488,7 @@ sub read_and_parse_old_spec {
}
if ( /^%description\b/i ) {
change_section("description");
$_ =~ s/^(%\w+)/lc($1)/e;
push @oldspec, $_;
($current_package, $current_lang) = set_current_pkg ( $_ );
my $target = $current_package;
$target .= "_$current_lang" if $current_lang;
$target .= "_disabled" if $ifhandler->{"disabled"};
push @oldspec, "XXXDESCRIPTION $target";
next;
}
if ( /^%install\b/i ) {
@ -363,64 +515,56 @@ sub read_and_parse_old_spec {
}
push @oldspec, "$_";
# multiline macros need an extra newline with old RPMs
if (/^%(\w[\w\d]+).*[^\\]$/) {
push @oldspec, "" if (defined($multiline_macros{$1}));
}
next;
}
if ($current_section eq "header") {
my $c_pack = $current_package;
$c_pack .= "_disabled" if $ifhandler->{"disabled"};
if ( /^Summary\b\s*:\s*(.*)/i ) {
$replace_hash{"XXXSUMMARY $c_pack"} = sprintf("%-16s%s","Summary:", $1);
push @oldspec, "XXXSUMMARY $c_pack";
next;
}
if ( /^Group\b\s*:\s*(.*)/i ) {
$replace_hash{"XXXGROUP $c_pack"} = sprintf("%-16s%s", "Group:", $1);
push @oldspec, "XXXGROUP $c_pack";
next;
}
if ( /^Vendor:/ || /^Distribution:/ || /^Packager:/ ) {
next;
}
if ( /^Name\s*:\s*(.*)/i ) {
my $orig_name = $1;
my $changed_name = $orig_name;
$changed_name =~ s/\Q$_\E/$definelist->{$_}/ for (sort { length($b) <=> length($a) } keys (%{$definelist}));
if ($changed_name eq $base_package) {
push @oldspec, sprintf("\n%-16s%s","Name:", $orig_name);
} else {
push @oldspec, sprintf("\n%-16s%s","Name:", $base_package);
}
$definelist->{"%name"} = $base_package if $ifhandler->{"disabled"} == 0;
$definelist->{"%{name}"} = $base_package if $ifhandler->{"disabled"} == 0;
warn ("line is $_, orig_name is $orig_name, base_package is $base_package\n") if $ifhandler->{"disabled"} == 0 && $debug;
next;
# remove default value of Autoreqprov
if ( /^Autoreqprov\s*:\s*(.*)/i ) {
next if ( lc($1) eq "on" || lc($1) eq "yes");
}
# reset Release
if ( /^Release\s*:\s*(.*)/i ) {
# will be after Version
next;
}
if ( /^Summary\s*:\s*(.*)\s*$/i ) {
push @oldspec, sprintf("%-16s%s", "Summary:", $1);
push @oldspec, "XXXPOSTSUMMARY $current_package";
next;
}
# remove license and print out after license later
if ( /^License\s*:\s*(.*)\s*$/i || /^Copyright\s*:\s*(.*)\s*$/i ) {
my $license = replace_spdx($1);
$main_license = $license if (!$main_license);
$seen_licenses{$current_package} = $license;
next;
}
# remove groups and print out after summary later
if ( /^Group\s*:\s*(.*)\s*$/i ) {
my $group = $1;
$main_group = $group if (!$main_group);
$seen_groups{$current_package} = $group;
next;
}
if ( /^BuildArchitectures\s*:/i ) {
$_ =~ s/^[^:]+:/BuildArch:/;
}
if ( /^Release\s*:\s*(.*)/i ) {
$pkg_release{$c_pack} = $_;
$replace_hash{"XXXRELEASE $c_pack"} = sprintf("%-16s%s","Release:", $1);
next;
}
if ( /^BuildRoot\s*:/i ) {
push @oldspec, "BuildRoot: %{_tmppath}/%{name}-%{version}-build";
next;
}
if ( /^Copyright\s*:\s*(.*)/i || /^License\s*:\s*(.*)/i ) {
$replace_hash{"XXXLICENSE $c_pack"} = sprintf("%-16s%s","License:", $1);
push @oldspec, "XXXLICENSE $c_pack";
next;
}
if ( /^Url\s*:\s*(.*)/i ) {
$replace_hash{"XXXURL $c_pack"} = sprintf("%-16s%s","Url:", $1);
push @oldspec, "XXXURL $c_pack";
next;
}
if ( m/$global_tags_re\s*(.*)/oi ) {
my ($tag, $value) = ($1, $2);
$nosrc_result = 1 if ($tag =~ /(?:nosource|nopatch)/i);
@ -431,24 +575,17 @@ sub read_and_parse_old_spec {
warn "found Version, section = $current_section\n" if $debug;
$version{$c_pack} = $_;
$version{$c_pack} =~ s/^Version:\s*(.*)\s*/$1/;
$replace_hash{"XXXVERSION $c_pack"} = sprintf("%-16s%s","Version:",$version{$c_pack});
push @oldspec, $replace_hash{"XXXVERSION $c_pack"};
push @oldspec, "XXXRELEASE $c_pack";
push @oldspec, sprintf("%-16s%s","Version:",$version{$c_pack});
push @oldspec, sprintf("%-16s%s","Release:", "0");
next;
}
}
if ( $current_section eq "description" ) {
my $target = $current_package;
$target .= "_$current_lang" if $current_lang;
$target .= "_disabled" if $ifhandler->{"disabled"};
$replace_hash{"XXXDESCRIPTION $target"} .= "\n" if ( $replace_hash{"XXXDESCRIPTION $target"} );
$replace_hash{"XXXDESCRIPTION $target"} .= $_;
if ( $current_section ne "changelog" ) {
push @oldspec, $_;
next;
}
if ( $current_section ne "description" && $current_section ne "changelog" ) {
push @oldspec, $_;
}
}
}
if ($ARGV[0] eq '--debug') {
@ -518,16 +655,40 @@ if ( ! stat ((glob("$specdir/$base_package*.spec"))[0] || "") ) {
read_and_parse_old_spec ( $specfile, $base_package );
for (@oldspec) {
next unless /^XXX/;
$please_replace{$_} = 1;
my $linesmoved = 1;
while ($linesmoved) {
$linesmoved = 0;
my @firstlines = ();
my @buildrequires = ();
while ($oldspec[0]) {
my $l = shift @oldspec;
if ($l =~ m/^BuildRequires:/ ) {
push(@buildrequires, $l);
} else {
# if there are already buildrequires, we need to sort and exit
if (@buildrequires > 0) {
my @sortedbrs = sort(@buildrequires);
$linesmoved = !compare_arrays(\@buildrequires, \@sortedbrs);
@oldspec = (@firstlines, sort(@buildrequires), $l, @oldspec);
@firstlines = ();
@buildrequires = ();
last;
} else {
push(@firstlines, $l);
}
}
}
@oldspec = (@firstlines, @oldspec);
}
my $thisyear = localtime->year() + 1900;
unshift @copyrights, "# Copyright (c) $thisyear SUSE LINUX Products GmbH, Nuernberg, Germany.";
my $copy_list = join("\n", @copyrights);
print $vim_modeline . "\n" if (defined $vim_modeline);
print <<EOF;
#
# spec file for package $base_package
@ -545,40 +706,39 @@ $copy_list
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
EOF
print "# norootforbuild\n" if $norootforbuild;
print "# needsrootforbuild\n" if $needsrootforbuild;
print "# needsbinariesforbuild\n" if $needsbinariesforbuild;
print "# nodebuginfo\n" if $nodebuginfo;
print "# icecream $icecreamforbuild\n" if $icecreamforbuild ne '';
print "\n";
print "\n" if ($needsrootforbuild || $needsbinariesforbuild || $nodebuginfo || $icecreamforbuild ne '');
while ($oldspec[0] eq "XXXBLANKLINE") {
shift @oldspec;
}
my $license_unique = !grep { $_ ne $main_license } values %seen_licenses;
my $groups_unique = !grep { $_ ne $main_group } values %seen_groups;
my $first_summary = 1;
my $line;
while (@oldspec) {
$line = shift @oldspec;
if ($line eq "XXXBLANKLINE") {
print "\n" unless $oldspec[0] && ($oldspec[0] eq "XXXBLANKLINE" || $oldspec[0] =~ /^\s*$/ || $oldspec[0] =~ /^\n/);
} elsif ($line =~ /^XXX/) {
print "DEBUG: replacing $line\n" if $debug;
print "$replace_hash{$line}\n";
} else {
print "$line\n";
# a package line with no license tag found for it yet
# if line ends with "\", we are probably in a macro definition
if ($line =~ /^%package/ && $line !~ /\\$/) {
$line =~ s/^(%\w+)/lc($1)/e;
my ($current_package, $current_lang) = set_current_pkg ( $line );
unless ($please_replace{"XXXLICENSE $current_package"} || !$replace_hash{"XXXLICENSE $current_package"}) {
print $replace_hash{"XXXLICENSE $current_package"}."\n";
}
$line = shift @oldspec;
if ($line eq "XXXBLANKLINE") {
print "\n" unless $oldspec[0] && ($oldspec[0] =~ m/^XXX.*LINE/ || $oldspec[0] =~ /^\s*$/ || $oldspec[0] =~ /^\n/);
} elsif ($line eq "XXXDOUBLELINE") {
print "\n\n" unless $oldspec[0] && ($oldspec[0] =~ m/^XXX.*LINE/ || $oldspec[0] =~ /^\s*$/ || $oldspec[0] =~ /^\n/);
} elsif ($line =~ m/XXXPOSTSUMMARY (.*)$/) {
my $current_package = $1;
my $license = $seen_licenses{$current_package} || $main_license;
printf("%-16s%s\n", "License:", $license) if (!$license_unique || $first_summary);
my $group = $seen_groups{$current_package} || $main_group;
printf("%-16s%s\n", "Group:", $group) if (!$groups_unique || $first_summary);
$first_summary = 0;
} else {
print "$line\n";
}
}
}
print "\n" unless $line eq "XXXBLANKLINE";