Michal Marek 411abb
#!/usr/bin/perl
Michal Marek 411abb
Michal Marek 411abb
use strict;
Michal Marek 411abb
use warnings;
Michal Marek 411abb
Michal Marek 411abb
use File::Copy;
Michal Marek 411abb
use Getopt::Long;
Michal Marek 411abb
Michal Marek 411abb
my $dir = ".";
Michal Marek cf65a8
my $rpmrelease;
Michal Marek 411abb
my $patches="";
Michal Marek 411abb
Michal Marek 411abb
GetOptions(
Michal Marek 411abb
	"patches=s" => \$patches,
Michal Marek 411abb
	"release=s" => \$rpmrelease
Michal Marek 411abb
) or die "Usage: $0 [--release <release>] [--patches <dir>]\n";
Michal Marek 411abb
Michal Marek 411abb
# flavor -> [supported archs]
Michal Marek 411abb
my %flavor_archs = parse_config_conf();
Michal Marek 411abb
# subset to include in kernel-syms
Michal Marek 411abb
my %syms_flavor_archs = parse_config_conf("syms");
Michal Marek 411abb
Michal Suchanek 2d4764
my %all_archs = parse_config_conf("needs_updating");
Michal Suchanek 2d4764
my @all_archs;
Michal Suchanek 2d4764
	for my $flavor (keys(%all_archs)) {
Michal Suchanek 2d4764
		push(@all_archs, arch2rpm(@{$all_archs{$flavor}}));
Michal Suchanek 2d4764
	}
Michal Suchanek 2d4764
@all_archs = sort(uniq(@all_archs));
Michal Suchanek 2d4764
my $all_archs = join(" ", @all_archs);
Michal Suchanek 2d4764
Michal Marek 411abb
# template name -> template body
Michal Marek 411abb
my %templates = read_spec_templates();
Michal Marek 411abb
Michal Marek 09cb6b
my @kmps = read_kmps();
Michal Marek 09cb6b
Michal Marek 411abb
# config.sh variables
Michal Marek 411abb
my %vars = parse_config_sh();
Michal Suchanek 36ba90
my ($srcversion, $variant, $obs_build_variant) =
Michal Suchanek 36ba90
	($vars{'SRCVERSION'}, $vars{'VARIANT'}, $vars{'OBS_BUILD_VARIANT'});
Michal Suchanek 36ba90
$obs_build_variant = ($obs_build_variant ? $variant : "" );
Takashi Iwai cdf580
my $compress_modules = 'none';
Jiri Slaby c8b2d9
my $compress_vmlinux = 'gz';
Michal Suchanek 7c057c
my $build_dtbs = ();
Michal Suchanek 88241e
my $livepatch = "";
Nicolai Stange 9d4124
my $livepatch_rt = "";
Takashi Iwai cdf580
if (defined($vars{'COMPRESS_MODULES'})) {
Takashi Iwai cdf580
	$compress_modules = $vars{'COMPRESS_MODULES'};
Takashi Iwai cdf580
}
Jiri Slaby c8b2d9
if (defined($vars{'COMPRESS_VMLINUX'})) {
Jiri Slaby c8b2d9
	$compress_vmlinux = $vars{'COMPRESS_VMLINUX'};
Jiri Slaby c8b2d9
}
Michal Suchanek 7c057c
if (defined($vars{'BUILD_DTBS'})) {
Michal Suchanek 7c057c
	$build_dtbs = $vars{'BUILD_DTBS'};
Michal Suchanek 7c057c
	$build_dtbs = () if $build_dtbs =~ /^(0+|no|false)$/i;
Michal Suchanek 7c057c
}
Michal Suchanek 88241e
if (defined($vars{'LIVEPATCH'})) {
Michal Suchanek 88241e
	$livepatch = $vars{'LIVEPATCH'};
Michal Suchanek 88241e
	$livepatch = "" if $livepatch =~ /^(0+|no|none)$/i;
Michal Suchanek 88241e
}
Nicolai Stange 9d4124
if (defined($vars{'LIVEPATCH_RT'})) {
Nicolai Stange 9d4124
	$livepatch_rt = $vars{'LIVEPATCH_RT'};
Nicolai Stange 9d4124
	$livepatch_rt = "" if $livepatch_rt =~ /^(0+|no|none)$/i;
Nicolai Stange 9d4124
}
Michal Marek cf65a8
if (!defined ($rpmrelease)) {
Michal Marek cf65a8
	$rpmrelease = $vars{'RELEASE'} || 0;
Michal Marek cf65a8
}
Michal Marek 411abb
Michal Marek 88d612
# package name -> [summary, description, extra kmp deps]
Michal Marek 411abb
my %binary_descriptions = parse_descriptions();
Michal Marek 411abb
Michal Marek 4037e1
# arch -> flavor -> [obsoleted packages]
Michal Marek 4037e1
my %obsolete_packages = parse_old_flavors();
Michal Marek 4037e1
Michal Marek 411abb
$patches="--patches $patches" if $patches;
Michal Marek 411abb
my $patchversion = `$dir/compute-PATCHVERSION.sh $patches`;
Michal Marek 411abb
chomp $patchversion;
Michal Marek 8d9b2b
my $rpmversion = $patchversion;
Michal Marek 8d9b2b
# stuff the -rcX tag into the rpm version if possible;
Takashi Iwai f37613
$rpmversion =~ s/\.0-rc/~rc/;
Michal Marek 8d9b2b
$rpmversion =~ s/-rc\d+//;
Michal Marek 8d9b2b
$rpmversion =~ s/-/./g;
Michal Marek 8d9b2b
Michal Marek 411abb
$rpmrelease =~ s/-/./g;
Michal Marek 411abb
Michal Marek 0b9e9a
my $sources = join("\n", $templates{source} =~ /^Source\d+:[^\n]*/msg);
Michal Suchanek e76c4c
# Do not include the signature and keyring as source in the binary packages
Michal Suchanek e76c4c
# The sources are not really included anyway, and for non-upstream tarballs these files do not exist
Michal Suchanek e76c4c
$sources = join("\n", grep { $_ !~ /[.](?:keyring|tar[.]sign)\s*$/ } $sources =~ /^[^\n]*/msg);
Michal Marek d12c88
# Find all SourceN: foo.tar.(bz2|xz) lines and generate the NoSource:
Michal Marek 411abb
# lines and the %setup line
Michal Marek 0b9e9a
my @tarballs = ($sources =~ /^Source(\d+):[^\n]*\.tar\.(?:bz2|xz)/msg);
Jan Moskyto Matejka afe62e
my $nosource = $sources;
Michal Marek 632061
$nosource =~ s/^Source(\d+):.*?$/NoSource:       $1/mg;
Jan Moskyto Matejka afe62e
Michal Marek 411abb
# Source0 (the linux tarball) is unpacked manually
Michal Marek 411abb
@tarballs = grep { $_ > 0 } @tarballs;
Michal Marek 411abb
my $unpack_patches = join(" ", map { "-a $_" } @tarballs);
Michal Marek 411abb
# List of scripts to automatically chmod +x before build
Michal Marek 411abb
my $scripts = join(",", grep { is_script($_) }
Michal Marek 411abb
			($sources =~ /\nSource\d+:\s*([^\s]*)/mg));
Michal Marek 411abb
Michal Marek 1548da
my $tarball_url;
Michal Marek 1548da
if ($srcversion =~ /^(\d+)(?:\.\d+)*(-rc\d+)?$/) {
77b5f8
	$tarball_url = "https://www.kernel.org/pub/linux/kernel/v$1.x/";
Michal Suchanek c4ef18
	$tarball_url = "" if $2; # kernel.org has no tarballs for rc kernels
Michal Suchanek c4ef18
	# rc tarballs only available from git as https://git.kernel.org/torvalds/t/linux-*.gz
Michal Marek 1548da
} else {
Michal Marek 1548da
	# kernel.org has no tarballs for  linux-next or vanilla snapshots
Michal Marek 1548da
	$tarball_url = "";
Michal Marek 1548da
}
Michal Marek 1548da
Michal Marek a80e5e
my $commit = get_commit();
Michal Suchanek b6fccd
my $commit_full = get_commit(1);
Michal Marek a80e5e
Michal Marek 411abb
my %macros = (
Michal Marek 411abb
	VARIANT => $variant,
Michal Suchanek 36ba90
	OBS_BUILD_VARIANT => $obs_build_variant . "%{nil}",
Michal Marek 411abb
	SRCVERSION => $srcversion,
Michal Marek 411abb
	PATCHVERSION => $patchversion,
Michal Marek 411abb
	RPMVERSION => $rpmversion,
Michal Marek 1548da
	TARBALL_URL => $tarball_url,
Michal Marek aebe2d
	RELEASE => $rpmrelease,
Michal Marek a80e5e
	COMMIT => $commit,
Michal Suchanek b6fccd
	COMMIT_FULL => $commit_full,
Michal Suchanek 403d89
	SOURCES => $sources . "\n# These files are found in the kernel-source package:\n" . $nosource,
Michal Marek 411abb
	UNPACK_PATCHES => $unpack_patches,
Michal Marek 411abb
	SCRIPTS => $scripts,
Michal Suchanek 88241e
	LIVEPATCH => $livepatch,
Nicolai Stange 9d4124
	LIVEPATCH_RT => $livepatch_rt,
Michal Marek aebe2d
	YEAR => (localtime time)[5] + 1900,
Takashi Iwai cdf580
	COMPRESS_MODULES => $compress_modules,
Jiri Slaby c8b2d9
	COMPRESS_VMLINUX => $compress_vmlinux,
Michal Marek 411abb
);
Michal Marek 411abb
Michal Marek 411abb
# binary spec files
Michal Marek 09cb6b
my $kmp_definitions = "";
Michal Marek a3cd25
my @kmp_definitions;
Michal Marek 09cb6b
for my $kmp (@kmps) {
Michal Marek 88d612
	my ($summary, $description, $deps);
Michal Marek 09cb6b
	if (!exists($binary_descriptions{$kmp})) {
Michal Marek 09cb6b
		print STDERR "warning: no description for $kmp found\n";
Michal Marek 09cb6b
		($summary = $kmp) =~ s/-kmp$//;
Michal Marek 09cb6b
		$summary .= " kernel modules";
Michal Marek 09cb6b
		$description = "$summary.";
Michal Marek 88d612
		$deps = "";
Michal Marek 09cb6b
	} else {
Michal Marek 09cb6b
		$summary = $binary_descriptions{$kmp}->[0];
Michal Marek 09cb6b
		$description = $binary_descriptions{$kmp}->[1];
Michal Marek 88d612
		$deps = $binary_descriptions{$kmp}->[2];
Michal Marek 09cb6b
	}
Michal Marek a3cd25
	push(@kmp_definitions, expand_template("kmp",
Michal Marek 09cb6b
		KMP_NAME => $kmp,
Michal Marek 09cb6b
		KMP_SUMMARY => $summary,
Michal Marek 88d612
		KMP_DESCRIPTION => $description,
Michal Marek 88d612
		KMP_DEPS => $deps));
Michal Marek 09cb6b
}
Michal Marek a3cd25
$kmp_definitions = join("\n", @kmp_definitions);
Michal Marek a3cd25
Michal Marek 411abb
for my $flavor (sort keys(%flavor_archs)) {
Michal Marek 411abb
	my ($summary, $description);
Michal Marek 411abb
	if (!exists($binary_descriptions{"kernel-$flavor"})) {
Michal Marek 411abb
		print STDERR "warning: no description for kernel-$flavor found\n";
Michal Marek 411abb
		$summary = "The Linux Kernel";
Michal Marek 411abb
		$description = "The Linux Kernel.";
Michal Marek 411abb
	} else {
Michal Marek 411abb
		$summary = $binary_descriptions{"kernel-$flavor"}->[0];
Michal Marek 411abb
		$description = $binary_descriptions{"kernel-$flavor"}->[1];
Michal Marek 411abb
	}
Michal Marek 411abb
Michal Marek e3547a
	my %obsolete_macros;
Takashi Iwai 1fa25f
	for my $subpac ("", "-base", "-extra", "-devel", "-hmac", "-optional") {
Michal Marek e3547a
		(my $macro = "PROVIDES_OBSOLETES" . uc($subpac)) =~ s/-/_/;
Michal Marek e3547a
		$obsolete_macros{$macro} =
Michal Marek e3547a
			provides_obsoletes($flavor, $subpac, @{$flavor_archs{$flavor}});
Michal Marek e3547a
	}
Michal Marek e3547a
Michal Marek 411abb
	do_spec('binary', "kernel-$flavor.spec", %macros,
Michal Marek 411abb
		FLAVOR => $flavor,
Michal Marek 411abb
		SUMMARY => $summary,
Michal Marek 411abb
		DESCRIPTION => $description,
Michal Suchanek 48b03c
		ARCHS => join(" ", arch2rpm(@{$flavor_archs{$flavor}})),
Michal Marek bf655e
		COMMON_DEPS => $templates{common_deps},
Michal Marek 09cb6b
		KMPS => join(" ", @kmps),
Michal Marek 09cb6b
		KMP_DEFINITIONS => $kmp_definitions,
Michal Marek e3547a
		%obsolete_macros
Michal Marek 411abb
	);
Michal Marek 411abb
}
Michal Marek 411abb
# kernel-source.spec
Michal Suchanek 48b03c
do_spec('source', "kernel-source$variant.spec", %macros);
Michal Marek 411abb
Michal Suchanek 045f5a
if ($variant eq "") {
Michal Suchanek 045f5a
	# kernel-docs.spec
Michal Suchanek 045f5a
	do_spec('docs', "kernel-docs$variant.spec", %macros);
Michal Suchanek 045f5a
}
Michal Marek 411abb
Michal Marek 411abb
# kernel-syms.spec
Michal Marek 411abb
{
Michal Marek 411abb
	my $requires = "";
Michal Suchanek 2d4764
	my %syms_archs;
Michal Suchanek 2d4764
	my $syms_archs;
Michal Marek 411abb
	for my $flavor (sort keys(%syms_flavor_archs)) {
Michal Marek 411abb
		next if $flavor eq "vanilla";
Michal Marek 411abb
		my @archs = arch2rpm(@{$syms_flavor_archs{$flavor}});
Michal Suchanek 2d4764
		$syms_archs{$_} = 1 for @archs;
Michal Marek 411abb
		$requires .= "%ifarch @archs\n";
Michal Marek 411abb
		$requires .= "Requires:       kernel-$flavor-devel = \%version-\%source_rel\n";
Michal Marek 411abb
		$requires .= "%endif\n";
Michal Marek 411abb
	}
Michal Marek 411abb
	chomp $requires;
Michal Suchanek 2d4764
	$syms_archs = join(" ", sort(keys(%syms_archs)));
Michal Suchanek 2d4764
	if (keys(%syms_archs)) {
Michal Marek eb17bb
		do_spec('syms', "kernel-syms$variant.spec", %macros,
Michal Marek eb17bb
			REQUIRES => $requires,
Michal Suchanek 2d4764
			ARCHS => $syms_archs);
Michal Marek b2e5f7
	}
Michal Marek f73ceb
}
Michal Marek f73ceb
Michal Marek f73ceb
# kernel-obs-*.spec
Michal Suchanek 36ba90
if (!$variant || $obs_build_variant) {
Michal Marek 022e5f
	my @default_archs;
Michal Suchanek 36ba90
	my $flavor = $obs_build_variant;
Michal Suchanek 36ba90
	if ($flavor) {
Michal Suchanek 36ba90
		$flavor =~ s/^-//;
Michal Marek 022e5f
	} else {
Michal Suchanek 36ba90
		$flavor = 'default';
Michal Marek 022e5f
	}
Michal Suchanek 36ba90
Michal Suchanek 36ba90
	@default_archs = arch2rpm(@{$flavor_archs{$flavor}});
Jiri Slaby 8099b4
	# No kernel-obs-* for 32bit ppc and x86
Jiri Slaby 8099b4
	@default_archs = grep { $_ ne "ppc" && $_ ne '%ix86' } @default_archs;
Michal Marek d1e0be
	my $default_archs = join(" ", @default_archs);
Michal Marek 022e5f
	do_spec('obs-build', "kernel-obs-build.spec", %macros,
Michal Marek 022e5f
		ARCHS => $default_archs);
Michal Marek 022e5f
	do_spec('obs-qa', "kernel-obs-qa.spec", %macros,
Michal Marek 022e5f
		ARCHS => $default_archs);
Michal Marek 411abb
}
Michal Marek b2e5f7
Michal Marek 797591
# dtb-*.spec
Michal Suchanek 36ba90
if ((!$variant || $obs_build_variant) && $build_dtbs) {
Michal Marek f3a989
	do_spec('dtb', "dtb.spec.in", %macros);
Michal Suchanek 8394ab
	print "./mkspec-dtb $all_archs\n";
Michal Suchanek 8394ab
	system("./mkspec-dtb $all_archs\n");
Michal Marek f3a989
	unlink("$dir/dtb.spec.in");
Michal Marek f3a989
	if ($?) {
Michal Marek f3a989
		exit(($? >> 8) || ($? & 127 + 128) || 1);
Michal Marek f3a989
	}
Michal Marek 797591
}
Michal Marek 797591
Michal Marek bd3c29
copy_changes();
Michal Marek 411abb
Michal Marek 65a07f
# _constraints
Michal Marek 65a07f
{
Michal Marek 65a07f
	my @packages = map { "<package>kernel-$_</package>" } sort keys(%flavor_archs);
Michal Marek 65a07f
	my $packages = join("\n", @packages);
Michal Marek 65a07f
	do_spec('constraints', "_constraints",
Michal Marek 65a07f
		BINARY_PACKAGES_XML => $packages);
Michal Marek 65a07f
}
Michal Marek 65a07f
Michal Marek 411abb
exit 0;
Michal Marek 411abb
Michal Marek 411abb
Michal Marek 411abb
Michal Marek 411abb
sub parse_config_conf {
Michal Marek 411abb
	my @symbols = @_;
Michal Marek 411abb
	my $symbols = join(' ', @symbols);
Michal Marek 411abb
	my %res;
Michal Marek 411abb
Michal Marek 411abb
	for my $arch (split(/\s+/, `$dir/arch-symbols --list`)) {
Michal Marek 411abb
		my @flavors = `$dir/guards $arch $symbols < $dir/config.conf`;
Michal Marek 411abb
		next if @flavors == 0;
Michal Marek 411abb
		chomp @flavors;
Michal Marek 411abb
		@flavors = map { s/.*\///; $_ } @flavors;
Michal Marek 411abb
		for my $flavor (@flavors) {
Michal Marek 411abb
			$res{$flavor} ||= [];
Michal Marek 411abb
			push(@{$res{$flavor}}, $arch);
Michal Marek 411abb
		}
Michal Marek 411abb
	}
Michal Marek 411abb
	for my $flavor (keys(%res)) {
Michal Marek 411abb
		$res{$flavor} = [sort @{$res{$flavor}}];
Michal Marek 411abb
	}
Michal Marek 411abb
	return %res;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 411abb
sub read_spec_templates {
Michal Marek 411abb
	my %res;
Michal Marek 411abb
Michal Suchanek a5ee24
	for my $template (qw(binary source syms docs obs-build obs-qa)) {
Michal Marek 411abb
		xopen(my $fh, '<', "$dir/kernel-$template.spec.in");
Michal Marek 411abb
		local $/ = undef;
Michal Marek 411abb
		$res{$template} = <$fh>;
Michal Marek 411abb
		close($fh);
Michal Marek bf655e
		next unless $template eq "binary";
Michal Marek bf655e
		if ($res{$template} =~ /^# BEGIN COMMON DEPS\n?(.*)^# END COMMON DEPS/ms) {
Michal Marek bf655e
			$res{common_deps} = $1;
Michal Marek bf655e
		} else {
Michal Marek bf655e
			print STDERR "warning: Expected # BEGIN COMMON DEPS in kernel-binary.spec.in\n";
Michal Marek bf655e
			$res{common_deps} = "";
Michal Marek bf655e
		}
Michal Marek 09cb6b
		if ($res{$template} =~ s/^# BEGIN KMP\n?(.*)^# END KMP/\@KMP_DEFINITIONS\@/ms) {
Michal Marek 09cb6b
			$res{kmp} = $1;
Michal Marek 09cb6b
		} else {
Michal Marek 09cb6b
			print STDERR "warning: Expected # BEGIN KMP in kernel-binary.spec.in\n";
Michal Marek 09cb6b
			$res{kmp} = "";
Michal Marek 09cb6b
		}
Michal Marek 411abb
	}
Michal Marek 65a07f
	{
Michal Marek 65a07f
		xopen(my $fh, '<', "$dir/constraints.in");
Michal Marek 65a07f
		local $/ = undef;
Michal Marek 65a07f
		$res{constraints} = <$fh>;
Michal Marek 65a07f
		close($fh);
Michal Marek 814c4e
		xopen($fh, '<', "$dir/dtb.spec.in.in");
Michal Marek 814c4e
		$res{dtb} = <$fh>;
Michal Marek 814c4e
		close($fh);
Michal Marek 65a07f
	}
Michal Marek 411abb
	return %res;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 411abb
# return a hash of config.sh variables
Michal Marek 411abb
sub parse_config_sh {
Michal Marek 411abb
	my %res;
Michal Marek 411abb
Michal Marek 411abb
	xopen(my $fh, '<', "$dir/config.sh");
Michal Marek 411abb
	while (<$fh>) {
Michal Marek 411abb
		chomp;
Michal Marek 411abb
		if (/^\s*([A-Z_]+)=(.*)/) {
Michal Marek cf65a8
			my ($key, $val) = ($1, $2);
Michal Marek cf65a8
			$val =~ s/^"(.*)"$/$1/;
Michal Marek cf65a8
			$res{$key} = $val;
Michal Marek 411abb
		}
Michal Marek 411abb
	}
Michal Marek 411abb
	close($fh);
Michal Marek 411abb
	return %res;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 411abb
sub parse_descriptions {
Michal Marek 411abb
	my %res;
Michal Marek 411abb
	my $current;
Michal Marek 411abb
	my $blank = "";
Michal Marek 411abb
	# 0 - expect summary, 1 - eating blank lines, 2 - reading description
Michal Marek 411abb
	my $state = 0;
Michal Marek 411abb
Michal Marek 411abb
	xopen(my $fh, '<', "$dir/package-descriptions");
Michal Marek 411abb
	while (<$fh>) {
Michal Marek 411abb
		next if /^\s*#/;
Michal Marek 411abb
Michal Marek 411abb
		if (/^==+\s+([^\s]+)\s+==+\s*$/) {
Michal Marek 411abb
			my $package = $1;
Michal Marek 411abb
			if ($current) {
Michal Marek 411abb
				chomp $current->[1];
Michal Marek 411abb
			}
Michal Marek 88d612
			$current = ["", "", ""];
Michal Marek 411abb
			$res{$package} = $current;
Michal Marek 411abb
			$state = 0;
Michal Marek 411abb
			next;
Michal Marek 411abb
		}
Michal Marek 411abb
		if (/^$/) {
Michal Marek 88d612
			if ($state == 0) {
Michal Marek 88d612
				$state++;
Michal Marek 88d612
			} elsif ($state == 2) {
Michal Marek 411abb
				$blank .= $_;
Michal Marek 411abb
			}
Michal Marek 411abb
			next;
Michal Marek 411abb
		}
Michal Marek 411abb
		# non-blank line and not === package ===
Michal Marek 411abb
		if ($state == 0) {
Michal Marek 411abb
			chomp;
Michal Marek 88d612
			if (s/^Requires: *//) {
Michal Marek 88d612
				# foo-kmp is a shorthand for another kmp
Michal Marek 88d612
				# from the same specfile
Michal Marek 88d612
				s/-kmp/-kmp-%build_flavor = %version-%release/g;
Michal Marek 88d612
				s/^/Requires:       /;
Michal Marek 88d612
				if ($current->[2]) {
Michal Marek 88d612
					$current->[2] .= "\n";
Michal Marek 88d612
				}
Michal Marek 88d612
				$current->[2] .= $_;
Michal Marek 88d612
			} else {
Michal Marek 88d612
				# The Summary: keyword is optional
Michal Marek 88d612
				s/^Summary: *//;
Michal Marek 88d612
				if ($current->[0]) {
Michal Marek 88d612
					print STDERR "warning: multi-line summary\n";
Michal Marek 88d612
				}
Michal Marek 88d612
				$current->[0] = $_;
Michal Marek 88d612
			}
Michal Marek 411abb
		} elsif ($state == 1) {
Michal Marek 411abb
			$current->[1] = $_;
Michal Marek 411abb
			$blank = "";
Michal Marek 88d612
			$state++;
Michal Marek 411abb
		} else {
Michal Marek 411abb
			$current->[1] .= $blank;
Michal Marek 411abb
			$blank = "";
Michal Marek 411abb
			$current->[1] .= $_;
Michal Marek 411abb
		}
Michal Marek 411abb
	}
Michal Marek 411abb
	if ($current) {
Michal Marek 411abb
		chomp $current->[1];
Michal Marek 411abb
	}
Michal Marek 411abb
	close($fh);
Michal Marek 411abb
	return %res;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 09cb6b
sub read_kmps {
Michal Marek 09cb6b
	my %res;
Michal Marek 09cb6b
Michal Marek 09cb6b
	open(my $fh, '-|', "$dir/guards", "--list", "--with-guards",
Michal Marek 09cb6b
		"-c", "$dir/supported.conf") or die "Error running guards: $!\n";
Michal Marek 09cb6b
	while (<$fh>) {
Michal Marek 09cb6b
		my @guards = split(' ');
Michal Marek 09cb6b
		pop(@guards);
Michal Marek 09cb6b
		for my $g (@guards) {
Michal Marek 09cb6b
			if ($g =~ /^\+(.*-kmp)$/) {
Michal Marek 09cb6b
				$res{$1} = 1;
Michal Marek 09cb6b
			}
Michal Marek 09cb6b
		}
Michal Marek 09cb6b
	}
Michal Marek 09cb6b
	close($fh) or die "Error running guards: $!\n";
Michal Marek 09cb6b
	return sort(keys(%res));
Michal Marek 09cb6b
}
Michal Marek 09cb6b
Michal Marek 4037e1
sub parse_old_flavors{
Michal Marek 4037e1
	my %res;
Michal Marek 4037e1
Michal Marek 4037e1
Michal Marek 4037e1
	xopen(my $fh, '<', "$dir/old-flavors");
Michal Marek 4037e1
	while (<$fh>) {
Michal Marek 4037e1
		chomp;
Michal Marek 4037e1
		next if /^\s*(#|$)/;
Michal Marek 25c1b0
		if (!m:^\s*(\w+)/([\w-]+)\s+([\w-]+)\s+([\w.-]+)\s*$:) {
Michal Marek 25c1b0
			print STDERR "$dir/old-flavors:$.: expected arch/flavor <old flavor> <old version>\n";
Michal Marek 4037e1
			next;
Michal Marek 4037e1
		}
Michal Marek 25c1b0
		my ($arch, $flavor, $old_flavor, $old_version) = ($1, $2, $3, $4);
Michal Marek 4037e1
		$res{$arch} ||= {};
Michal Marek 4037e1
		$res{$arch}{$flavor} ||= [];
Michal Marek 25c1b0
		push(@{$res{$arch}{$flavor}},
Michal Marek 25c1b0
			["kernel-$old_flavor", $old_version]);
Michal Marek 4037e1
	}
Michal Marek 4037e1
	close($fh);
Michal Marek 4037e1
	return %res;
Michal Marek 4037e1
}
Michal Marek 4037e1
Michal Marek 411abb
sub is_script {
Michal Marek 411abb
	my $script = shift;
Michal Marek 411abb
Michal Marek 411abb
	return undef if $script =~ /\.(tar\.(gz|bz2)|in|conf)$/;
Michal Marek 411abb
	return undef if $script =~ /^README/;
Michal Marek 411abb
	return 1 if $script =~ /\.pl$/;
Michal Marek 411abb
	open(my $fh, '<', $script) or return undef;
Michal Marek 411abb
	sysread($fh, my $shebang, 2);
Michal Marek 411abb
	close($fh);
Michal Marek 411abb
	return 1 if $shebang eq "#!";
Michal Marek 411abb
	return undef;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 411abb
sub arch2rpm {
Michal Marek 411abb
	if (wantarray) {
Michal Marek 411abb
		return map { _arch2rpm($_) } @_;
Michal Marek 411abb
	}
Michal Marek 411abb
	return _arch2rpm($_[0]);
Michal Marek 411abb
}
Michal Marek 411abb
sub _arch2rpm {
Michal Marek 411abb
	my $arch = shift;
Michal Marek 411abb
	return "\%ix86" if $arch eq "i386";
Alexander Graf 09220e
	return "aarch64" if $arch eq "arm64";
Michal Marek 411abb
	return $arch;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 411abb
sub provides_obsoletes {
Michal Marek 411abb
	my $flavor = shift;
Michal Marek e3547a
	my $subpac = shift;
Michal Marek 411abb
	my @archs = @_;
Michal Marek 411abb
	my $res = "";
Michal Marek 411abb
Michal Marek 411abb
	for my $arch (@archs) {
Michal Marek 4037e1
		my @packs = @{$obsolete_packages{$arch}{$flavor} || []};
Michal Marek e3547a
		my $printed;
Michal Marek e3547a
Michal Marek 411abb
		next if (!@packs);
Michal Marek 411abb
		my $rpmarch = arch2rpm($arch);
Michal Marek 411abb
		chomp $rpmarch;
Michal Marek 25c1b0
		for my $pack (@packs) {
Michal Marek e3547a
			my $name = $pack->[0] . $subpac;
Michal Marek 25c1b0
			my $version = $pack->[1];
Michal Marek e3547a
			if ($subpac) {
Michal Marek e3547a
				# The -base and -extra split has been
Michal Marek e3547a
				# introduced in SLE11 (2.6.27)
Michal Marek e3547a
				my ($v1, $v2, $v3) = split(/\./, $version);
Michal Marek e3547a
				next if ($v1 <= 2 && $v2 <= 6 && $v3 < 27);
Michal Marek e3547a
			}
Michal Marek e3547a
			if (!$printed) {
Michal Marek e3547a
				$res .= "\%ifarch $rpmarch\n";
Michal Marek e3547a
				$printed = 1;
Michal Marek e3547a
			}
Michal Marek 25c1b0
			$res .= "Provides:       $name = $version\n";
Michal Marek 25c1b0
			$res .= "Obsoletes:      $name <= $version\n";
Michal Marek 25c1b0
		}
Michal Marek e3547a
		$res .= "\%endif\n" if $printed;
Michal Marek 411abb
	}
Michal Marek 411abb
	chomp $res;
Michal Marek 411abb
	return $res;
Michal Marek 411abb
}
Michal Marek 411abb
Michal Suchanek f15670
sub get_commit {
Michal Suchanek b6fccd
	my ($commit, $fh, $full);
Michal Suchanek b6fccd
Michal Suchanek b6fccd
	$full = $_[0] // 0;
Michal Marek a80e5e
Michal Marek a80e5e
	if (!open($fh, '<', "source-timestamp")) {
Michal Marek a80e5e
		print STDERR "warning: source-timestamp: $!\n";
Michal Marek a80e5e
		print STDERR "warning: Cannot determine commit id\n";
Michal Marek a80e5e
		return "0000000";
Michal Marek a80e5e
	}
Michal Marek a80e5e
	while (<$fh>) {
Michal Suchanek b6fccd
		if ($full ? /^GIT Revision: ([0-9a-f]{40})/ : /^GIT Revision: ([0-9a-f]{7})/) {
Michal Marek a80e5e
			$commit = $1;
Michal Marek a80e5e
		}
Michal Marek a80e5e
	}
Michal Marek a80e5e
	close($fh);
Michal Marek a80e5e
	if (!$commit) {
Michal Marek a80e5e
		print STDERR "warning: Commit id missing in source-timestamp file\n";
Michal Marek a80e5e
		return "0000000";
Michal Marek a80e5e
	}
Michal Marek a80e5e
	return $commit;
Michal Marek a80e5e
}
Michal Marek a80e5e
Michal Marek 09cb6b
sub expand_template {
Michal Marek 411abb
	my $template = shift;
Michal Marek 411abb
	my %macros = @_;
Michal Marek 411abb
Michal Marek 411abb
	my $text = $templates{$template};
Michal Marek 5453f9
	my $prev_text;
Michal Marek 5453f9
	do {
Michal Marek 5453f9
		$prev_text = $text;
Michal Marek 5453f9
		for my $m (keys %macros) {
Michal Marek a3cd25
			if ($macros{$m} eq "") {
Michal Marek a3cd25
				# Do not generate empty lines
Michal Marek a3cd25
				$text =~ s/^\@$m\@\n//mg;
Michal Marek a3cd25
			}
Michal Marek 5453f9
			$text =~ s/\@$m\@/$macros{$m}/g;
Michal Marek 5453f9
		}
Michal Marek 5453f9
	} while ($prev_text ne $text);
Michal Marek 09cb6b
	return $text;
Michal Marek 09cb6b
}
Michal Marek 09cb6b
Michal Marek 09cb6b
sub do_spec {
Michal Marek 09cb6b
	my $template = shift;
Michal Marek 09cb6b
	my $specfile = shift;
Michal Marek 09cb6b
	my %macros = @_;
Michal Marek 09cb6b
Michal Marek 09cb6b
	my $text = expand_template($template, %macros);
Michal Marek 411abb
	print "$specfile\n";
Michal Marek 411abb
	xopen(my $fh, '>', "$dir/$specfile");
Michal Marek 411abb
	print $fh $text;
Michal Marek 411abb
	close($fh);
Michal Marek bd3c29
}
Michal Marek bd3c29
Michal Marek bd3c29
sub copy_changes {
Michal Marek bd3c29
Michal Marek bd3c29
	opendir(my $dh, $dir) or die "$dir: $!\n";
Michal Marek bd3c29
Michal Marek ecf021
	while (my $name = readdir $dh) {
Michal Marek bd3c29
		next unless $name =~ /\.spec$/;
Michal Marek bd3c29
		next if $name eq "kernel-source$variant.spec";
Michal Marek bd3c29
Michal Marek bd3c29
		$name =~ s/\.spec$/.changes/;
Michal Marek bd3c29
		copy("$dir/kernel-source$variant.changes", "$dir/$name");
Michal Marek bd3c29
	}
Michal Marek bd3c29
	closedir($dh);
Michal Marek 411abb
}
Michal Marek 411abb
Michal Marek 411abb
sub xopen {
Michal Marek 411abb
        open($_[0], $_[1], $_[2]) or die "$_[2]: $!\n";
Michal Marek 411abb
}
Michal Marek 411abb
Michal Suchanek 2d4764
sub uniq {
Michal Suchanek 2d4764
	my %seen;
Michal Suchanek 2d4764
	return grep { !$seen{$_}++ } @_;
Michal Suchanek 2d4764
}