#!/usr/bin/perl -w
#
# Copyright (c) 2022 Adrian Schroeter, SUSE LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 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 Git LFS provider --- admin tool
#

BEGIN {
  my ($wd) = $0 =~ m-(.*)/- ;
  $wd ||= '.';
  unshift @INC,  "$wd";
}

use BSSQLite;
use Digest::SHA;
use Data::Dumper;

use strict;

my $db_file = "obs-git-lfs.db";

if (! -e "$db_file") {
  my $h = BSSQLite::connectdb($db_file);
  my %dbtables = map {$_ => 1} BSSQLite::list_tables($h);
  if (!$dbtables{'lfs_oids'}) {
    BSSQLite::dbdo($h, <<'EOS');
  CREATE TABLE IF NOT EXISTS lfs_oids(
    project TEXT,
    package TEXT,
    filename TEXT,
    rev TEXT,
    sha256 TEXT,
    size INTEGER,
    UNIQUE(project,package,rev,filename)
  )
EOS
  }
  BSSQLite::dbdo($h, 'CREATE INDEX IF NOT EXISTS oid_idx on lfs_oids(sha256,size)');
}

my $projid;
my $packid;
my $filename;
my $rev;
my $sha256;
my $size;

if (@ARGV == 4) {
  ($projid, $packid, $rev, $filename) = @ARGV;
  my $fd;
  open($fd, '<', $filename) || die("$filename $!\n");
  $size = -s $fd;
  my $ctx = Digest::SHA->new(256);
  $ctx->addfile($fd);
  close($fd);
  $sha256 = $ctx->hexdigest();
  $filename =~ s/.*\///;
  print " $size $sha256 $filename\n";
} elsif (@ARGV == 6){
  ($projid, $packid, $rev, $filename, $sha256, $size) = @ARGV;
} else {
  print "I need exactly these parameters in this order:\n";
  print "  project package source-revision-of-expanded-package filename file-sha256 file-size-in-byte\n";
  print "or \n";
  print "  project package source-revision-of-expanded-package local_file_with_correct_filename\n";
  exit(1);
}

# normalize and verify
$rev = lc($rev);
$sha256 = lc($sha256);
$size = 0 + $size;
die("Revision must be a md5sum\n") unless $rev =~ /^[0-9a-f]{32}$/s;
die("Oid must be a sha256sum\n") unless $sha256 =~ /^[0-9a-f]{64}$/s;
die("Bad project\n") if !$projid || $projid =~ /[\/\000-\037]/  || ":$projid:" =~ /:[_\.:]/;
die("Bad package\n") if !$packid || $packid =~ /[\/:\000-\037]/ || $packid =~ /^[_\.]/;
die("Bad filename\n") if $filename =~ /[\/\000-\037]/ || $filename =~ /^\./;
die("Bad size\n") if $size < 0;

# add to database
my $h = BSSQLite::connectdb($db_file);
BSSQLite::begin_work($h);
BSSQLite::dbdo_bind($h, 'INSERT OR IGNORE INTO lfs_oids(project,package,filename,rev,sha256,size) VALUES(?,?,?,?,?,?)', [ $projid ], [ $packid ], [ $filename ], [ $rev ], [ $sha256 ], [ $size ]);
BSSQLite::commit($h);

