#!/usr/bin/perl
use strict;
use warnings;
my $USAGE = "Usage: $0 <local package> <project> [<package>]\n";
BEGIN {
(my $path = $0) =~ s/^(.*?)[^\/]*$/$1/;
if ($path !~ /^\//) {
$path = "$ENV{'PWD'}/$path";
}
push @INC, "${path}lib";
$ENV{PATH} = "$ENV{PATH}:$path";
}
use Getopt::Long;
use SUSE::MyBS;
my $api;
my $verbose = 1;
my $no_init;
my $ignore_kabi;
my $debuginfo;
my $enable_checks;
my $rebuild;
my $submit;
my @maintainers;
my @limit_packages;
my @package_links;
GetOptions(
"A|apiurl=s" => \$api,
"i|ignore-kabi" => \$ignore_kabi,
"no-init" => \$no_init,
"c|enable-checks" => \$enable_checks,
"d|debuginfo" => \$debuginfo,
"r|rebuild" => \$rebuild,
"s|submit" => \$submit,
"maintainer=s" => \@maintainers,
"flavor=s" => \@limit_packages,
"q|quiet" => sub { $verbose = 0 },
"v|verbose" => \$verbose,
"h|help" => sub { print $USAGE; exit },
) or die($USAGE);
if (scalar(@ARGV) < 2 || @ARGV > 3 || !-d $ARGV[0]) {
die($USAGE);
}
my ($dir, $project, $package) = @ARGV[0..2];
$project =~ s/\//:/g;
if (!$package) {
($package = $dir) =~ s:/+\.?$::;
$package =~ s@.*/@@;
if (! -e "$dir/$package.spec") {
opendir(my $dh, $dir) or die;
my @specfiles = sort grep { /\.spec$/ } readdir($dh);
if (!@specfiles) {
die "No specfiles found in $dir and no package name specified\n";
}
closedir($dh);
($package = $specfiles[0]) =~ s/\.spec//;
}
}
if (@limit_packages) {
s/^kernel-// for @limit_packages;
s/^/kernel-/ for @limit_packages;
push(@limit_packages, $package);
}
my ($branch, $commit) = get_git_info($dir);
if ($commit) {
$commit = "commit $commit";
} else {
print STDERR "warning: $dir does not look like a kernel package\n";
$commit = ".";
}
my $bs = SUSE::MyBS->new($api);
# hack for SLE12-SP1-ARM
my $BS_SUFFIX;
my %repos = get_repos($dir, $api);
die "Project not specified in config.sh\n" unless exists $repos{""};
my $qa;
if (glob("$dir/kernel-obs-*.spec")) {
$qa = 1;
}
my @archs = get_archs($dir);
if (!scalar(@archs)) {
warn "No ExclusiveArch: headers in $dir/*.spec\n";
}
if (!@limit_packages && !$BS_SUFFIX) {
# Include currently disabled flavors and archs
my @all_archs;
get_all_archs_flavors($dir, \@all_archs, \@package_links);
push(@archs, @all_archs);
s/^/kernel-/ for @package_links;
}
my @add_packages = ();
my @macros = ("%is_kotd 1");
if ($ignore_kabi) {
push(@macros, "%ignore_kabi_badness 1");
}
if (-e "$dir/klp-symbols") {
push(@macros, "%klp_symbols 1");
}
my @remove_packages = qw(kernel-dummy);
if (!$enable_checks) {
push(@remove_packages, "rpmlint-Factory",
"post-build-checks-malwarescan");
}
my $prjconf = "";
if (!-e "$dir/_constraints") {
my $need_gb = $debuginfo ? 14 : 4;
my $need_gb_2 = $need_gb / 2;
$prjconf =
"\%ifarch \%ix86 x86_64
Constraint: hardware:processors 8
\%endif
\%ifarch \%ix86 x86_64 ia64 ppc ppc64 ppc64le
Constraint: hardware:disk:size unit=G $need_gb
\%else
Constraint: hardware:disk:size unit=G $need_gb_2
\%endif
";
}
my $prj;
if ($no_init) {
$prj = $project;
} else {
$prj = $bs->create_project($project, {
repos => \%repos,
title => "Kernel builds for " . ($branch ? "branch $branch" : $commit),
build => 1,
publish => 1,
qa => $qa,
debuginfo => $debuginfo,
remove_packages => \@remove_packages,
add_packages => \@add_packages,
prjconf => $prjconf,
macros => \@macros,
limit_archs => \@archs,
maintainers => \@maintainers,
rebuild => $rebuild,
});
}
my $progress_cb;
if ($verbose) {
$progress_cb = \&progress_verbose;
} else {
$progress_cb = \&progress_silent;
}
my $rev = $bs->upload_package($dir, $prj, $package, $commit, {
no_init => $no_init,
progresscb => $progress_cb,
remove_packages => [qw(kernel-dummy)],
limit_packages => \@limit_packages,
extra_links => \@package_links,
});
if ($submit) {
if (!exists($repos{""})) {
die "No default submit target found in config.sh\n";
}
if (!$rev) {
exit 0;
}
&$progress_cb('SUBMIT', "$project/$package($rev)");
$bs->submit_package($project, $package, $rev, $repos{""}, $commit);
}
exit 0;
sub progress_verbose {
print join(" ", @_), "\n";
}
sub progress_silent {};
sub get_git_info {
my $dir = shift;
my $file = "$dir/source-timestamp";
if (! -f $file) {
$file = "$dir/build-source-timestamp"
}
if (! -f $file) {
return;
}
open(my $fh, '<', $file) or die "$file: $!\n";
my ($branch, $commit);
while (<$fh>) {
chomp;
if (s/^GIT Revision: //) {
$commit = $_;
}
if (s/^GIT Branch: //) {
$branch = $_;
}
}
close($fh);
return ($branch, $commit);
}
sub get_repos {
my ($dir, $api) = @_;
my $file = "$dir/config.sh";
my $want_ibs = ($api && $api =~ /\.suse\.de/);
my (%obs, %ibs);
open(my $fh, '<', $file) or die "$file: $!\n";
while (<$fh>) {
chomp;
if (/^BS_SUFFIX=(.*)/) {
$BS_SUFFIX = $1;
}
next unless /^(OBS|IBS)_PROJECT(_\w+)?=(.*)/;
my ($api, $repo, $project) = ($1, $2, $3);
next unless $project;
$repo ||= "";
$repo =~ s/^_//;
if ($api eq "OBS") {
$obs{$repo} = $project;
if (!exists($ibs{$repo})) {
$ibs{$repo} = "openSUSE.org:$project";
}
} else {
$ibs{$repo} = $project;
}
}
close($fh);
return %ibs if $want_ibs;
return %obs;
}
sub bs_arch {
my @res;
for my $a (@_) {
if ($a =~ /^%?i.86$/) {
push(@res, "i586");
} elsif ($a =~ /^armv(\d)h?l/) {
push (@res, "armv$1l", "armv$1hl");
} elsif ($a eq "arm64") {
push (@res, "aarch64");
} else {
push(@res, $a);
}
}
return @res;
}
sub get_archs {
my $dir = shift;
my %archs;
my %limit_specs;
$limit_specs{"$_.spec"} = 1 for @limit_packages;
opendir(my $dh, $dir) or return;
while (my $de = readdir($dh)) {
next unless $de =~ /\.spec$/;
next unless !@limit_packages || $limit_specs{$de};
my $f = "$dir/$de";
my $fh;
if (!open($fh, '<', "$f")) {
warn "warning: could not open $f: $!\n";
next;
}
while (<$fh>) {
chomp;
next unless s/^exclusivearch://i;
$archs{$_} = 1 for bs_arch(split);
last;
}
close($fh);
}
return sort(keys(%archs));
}
sub get_all_archs_flavors {
my ($dir, $archs, $flavors) = @_;
my (%archs, %flavors);
my $pipe;
return unless -e "$dir/config.conf";
if (!open($pipe, '-|', "guards", "--list", "--config", "$dir/config.conf")) {
warn "error running guards: $!\n";
return;
}
while (<$pipe>) {
chomp;
my ($arch, $flavor) = split(/\//);
$archs{$_} = 1 for bs_arch($arch);
$flavors{$flavor} = 1;
}
if (!close($pipe)) {
warn "guards returned an error\n";
}
@$archs = sort(keys(%archs));
@$flavors = sort(keys(%flavors));
}