#!/usr/bin/perl -w

################################################################
#
# Copyright (c) 2021 SUSE Linux GmbH
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################

# obs: repo support

BEGIN {
  unshift @INC, ($::ENV{"BUILD_DIR"} || "/usr/lib/build");
}

use strict;
use Digest::MD5 ();
use File::Path;
use Getopt::Long;
use Storable;

use Build ':rpm';

use PBuild::Download;
use PBuild::OBS;
use PBuild::Cpio;

Getopt::Long::Configure("no_ignore_case");

my $cachedir = "/var/cache/build";
my $obsurl;
my $arch;
my $reverse;
my $noexpand;

my $cmd = shift @ARGV;
die("please specify a query command\n") unless defined $cmd;

if ($cmd eq 'expandpath') {
  GetOptions('obs=s' => \$obsurl, 'reverse' => \$reverse) or exit(1);
  die("please specify a obs url with the --obs option\n")  unless $obsurl;
  $obsurl =~ s/\/$//;
  for my $url (@ARGV) {
    die("$url: not a valid  obs: repo") unless $url =~ /^obs:\/{1,3}([^\/]+\/[^\/]+)\/?$/;
    my $prp = $1;
    $prp =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/sge;
    my @prps = PBuild::OBS::expand_path($prp, "$obsurl/");
    @prps = reverse(@prps) if $reverse;
    for (@prps) {
      s/([\000-\040<>;\"#\?&\+=%[\177-\377])/sprintf("%%%02X",ord($1))/sge;
      print "obs:/$_\n";
    }
  }
  exit;
}

if ($cmd eq 'config') {
  GetOptions('obs=s' => \$obsurl, 'reverse' => \$reverse, 'noexpand' => \$noexpand) or exit(1);
  die("please specify a obs url with the --obs option\n")  unless $obsurl;
  $obsurl =~ s/\/$//;
  my @configs;
  my $distcnt = 0;
  for my $url (@ARGV) {
    $distcnt++;
    my $doexpand = $distcnt == @ARGV && !$noexpand ? 1 : 0;
    my ($obsconfigs) = PBuild::OBS::fetch_all_configs($url, { 'obs' => $obsurl }, $doexpand);
    @$obsconfigs = reverse @$obsconfigs unless $reverse;
    push @configs, @$obsconfigs;
  }
  my $config = Build::combine_configs(@configs);
  $config =~ s/\n?$/\n/s if $config ne '';
  print $config;
  exit;
}

die("unknown query command '$cmd'\n") unless $cmd eq 'repo';

GetOptions("cachedir=s" => \$cachedir, "obs=s" => \$obsurl, "arch=s" => \$arch) or exit(1);

die("please specify a obs url with the --obs option\n")  unless $obsurl;
$obsurl =~ s/\/$//;
die("please specify a scheduler architecture with the --arch option\n")  unless $arch;
$arch =~ s/:.*//;

for my $url (@ARGV) {
  die("$url: not a valid  obs: repo") unless $url =~ /^obs:\/{1,3}([^\/]+\/[^\/]+)\/?$/;
  my $prp = $1;
  my $repoid = Digest::MD5::md5_hex("$obsurl/build/$prp/$arch");
  my $dir = "$cachedir/$repoid";
  File::Path::mkpath($dir);
  PBuild::Download::download("$obsurl/build/$prp/$arch/_repository?view=cache", "$dir/repository.cpio");
  PBuild::Cpio::cpio_extract("$dir/repository.cpio", 'repositorycache', "$dir/repository.data");
  my $rdata = Storable::retrieve("$dir/repository.data");
  my @bins = grep {ref($_) eq 'HASH' && defined($_->{'name'})} values %{$rdata || {}};
  @bins = sort {$a->{'name'} cmp $b->{'name'}} @bins;
  for (@bins) {
    delete $_->{'filename'};    # just in case
    delete $_->{'packid'};      # just in case
    if ($_->{'path'} =~ /^\.\.\/([^\/\.][^\/]*\/[^\/\.][^\/]*)$/s) {
      $_->{'location'} = "$obsurl/build/$prp/$arch/$1";       # obsbinlink to package
    } else {
      $_->{'location'} = "$obsurl/build/$prp/$arch/_repository/$_->{'path'}";
    }
    PBuild::OBS::recode_deps($_);
    Build::writedeps(\*STDOUT, $_);
  }
}
