/usr/lib/obs/server/bs_mkarchrepo is in obs-server 2.7.4-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | #!/usr/bin/perl -w
BEGIN {
  my ($wd) = $0 =~ m-(.*)/- ;
  $wd ||= '.';
  unshift @INC,  "$wd/build";
  unshift @INC,  "$wd";
}
use strict;
use Digest;
use Digest::MD5;
use MIME::Base64;
use BSUtil;
use Build::Arch;
my %todo = (
  'desc' => [
    'FILENAME' => 'filename',
    'NAME' => 'pkgname',
    'BASE' => 'pkgbase',
    'VERSION' => 'pkgver',
    'DESC' => 'pkgdesc',
    'GROUPS' => 'group',
    'CSIZE' => 'filesize',
    'ISIZE' => 'size',
    'MD5SUM' => 'filemd5',
    'SHA256SUM' => 'filesha256',
    'PGPSIG' => 'pgpsig',
    'URL' => 'url',
    'LICENSE' => 'license',
    'ARCH' => 'arch',
    'BUILDDATE' => 'builddate',
    'PACKAGER' => 'packager',
    'REPLACES' => 'replaces',
  ],
  'depends' => [
    'DEPENDS' => 'depend',
    'CONFLICTS' => 'conflict',
    'PROVIDES' => 'provides',
    'OPTDEPENDS' => 'optdepend',
  ],
  'files' => [
    'FILES' => 'files',
  ],
);
die("Usage: bs_mkarchrepo <reponame> <dir>\n") unless @ARGV == 2;
my $reponame = $ARGV[0];
my $dir = $ARGV[1];
my @pkgs = grep {/\.pkg\.tar\.(?:gz|xz)$/} ls($dir);
my $rdir = "$dir/$reponame.db";
mkdir_p($rdir);
my @pd;
for my $pkg (@pkgs) {
  if (!open(F, '<', "$dir/$pkg")) {
    warn("$dir/$pkg: $!\n");
    next;
  }
  my @s = stat(F);
  next unless @s;
  my $ctx = Digest::MD5->new;
  $ctx->addfile(\*F);
  close F;
  if (!open(F, '<', "$dir/$pkg")) {
    warn("$dir/$pkg: $!\n");
    next;
  }
  my $ctxsha256 = Digest->new('SHA-256');
  $ctxsha256->addfile(\*F) if $ctxsha256;
  close F;
  my $vars;
  my $files;
  eval {
    $vars = Build::Arch::queryvars("$dir/$pkg");
    $files = Build::Arch::queryfiles("$dir/$pkg");
  };
  warn($@) if $@;
  next unless $vars;
  $vars->{'files'} = $files if $files;
  $vars->{'filename'} = [ $pkg ];
  $vars->{'filesize'} = [ $s[7] ];
  $vars->{'filemd5'} = [ $ctx->hexdigest ];
  $vars->{'filesha256'} = [ $ctxsha256->hexdigest ] if $ctxsha256;
  my $sig = readstr("$dir/$pkg.sig", 1);
  if ($sig && length($sig) <= 16384) {
    $sig = encode_base64($sig, '');
    $vars->{'pgpsig'} = $sig =~ /(.{1,64})/g;
  }
  
  my $d = "$vars->{'pkgname'}->[0]-$vars->{'pkgver'}->[0]";
  if (!mkdir("$rdir/$d")) {
    warn("$d: $!\n");
    next;
  }
  for my $t (sort keys %todo) {
    my @t = @{$todo{$t}};
    open(F, '>', "$rdir/$d/$t") || die("$rdir/$d/$t: $!\n");
    while (@t) {
      my ($tag, $source) = splice(@t, 0, 2);
      next unless @{$vars->{$source} || []};
      print F "\%$tag\%\n";
      print F "$_\n" for @{$vars->{$source}};
      print F "\n";
    }
    close(F) || die("close: $!\n");
  }
  push @pd, $d;
}
if (@pd) {
  unshift @pd, '--';
} else {
  push @pd, '-T', '/dev/null';
}
system('tar', '-czf', "$dir/$reponame.db.tar.gz", '--exclude', 'files', '-C', "$rdir", @pd);
system('tar', '-czf', "$dir/$reponame.files.tar.gz", '-C', "$rdir", @pd);
BSUtil::cleandir($rdir);
rmdir($rdir);
 |