#!/usr/bin/perl
#
# $Id$
#
# PBA archiver main program
#
# (C) IBCL Informatik-Buero e.U. 2010
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

use strict;

#use Date::Format;

require "/usr/lib/pba/archive-functions.pl";
require "/usr/lib/pba/pba-functions.pl";

$main::scriptName = "pba-archiver";

prepareGetopts();

initPBAFunctions();

initArchiveFunctions();

parseConfig();

checkArchiverConfig();

# start working

# search new binary package || exit 


if ($main::archiveOperation eq "list-archives") {
  # list archives
  ($main::verbosity > 0) && print "PBA-Archiver running in list mode.\n";

  my $repositoryRoot = $main::repositoryRoots{$main::targetRepository};
  my %foundArchives = ();
  my %archiveWarnings = ();
  my %foundOthers = ();
  chdir $repositoryRoot || cleanupAndDie("FATAL: Cannot chdir to ".$repositoryRoot."\n");
  my $findCmd = "find . -mindepth 2 -maxdepth 2 -type d -name dists";
  open (FINDOUTPUT, $findCmd."|") || cleanupAndDie("FATAL: Cannot search. Find command was:\n".$findCmd."\npwd was: ".pwd()."\n");
  while ( my $distsDir = <FINDOUTPUT> ) {
    chomp $distsDir;
    chdir $repositoryRoot."/".$distsDir || cleanupAndDie("FATAL: Cannot chdir to ".$distsDir."\n");
    my ($dot, $dcgFamily, $dists) = split /\//, $distsDir;
    my @subdirs = glob("*");
    foreach my $subdir (@subdirs) {
      next if (not -d $subdir);
      if ($subdir =~ /[a-z0-9_]+-[a-z0-9_]+-[a-z0-9_]/) {
        my ($dcgDistribution, $dcgCategory, $dcgGeneration) = split /-/, $subdir, 3;
        $foundArchives{$subdir} = $distsDir."/".$subdir;
        my $warnings = "";
        if (defined $main::distributionLongNames{$dcgDistribution}) {
          if ($main::distributionFamilies{$dcgDistribution} ne $dcgFamily) {
            $warnings .= "Familiy '".$dcgFamily."' does not match expected '".$main::distributionFamilies{$dcgDistribution}."'. ";
          }
        } else {
          $warnings .= "Distribution unknown: '".$dcgDistribution."'. ";
        }
        $archiveWarnings{$subdir} = $warnings;
      } else {
        $foundOthers{$subdir} = $distsDir."/".$subdir;
      }
    }
  }
  close FINDOUTPUT;

  ($main::verbosity > 0) && print "Found these distribution-category-generation archives:\n";
  foreach my $dcg (sort(keys(%foundArchives))) {
    if ( ($archiveWarnings{$dcg} eq "") or ($main::verbosity < 1) ) {
      print $dcg."\n";
    } else {
      print $dcg."\tWARNINGS: ".$archiveWarnings{$dcg}."\n";
    }
  }
  if ( ($main::verbosity > 0) and (scalar(keys(%foundOthers)) > 0) ) {
    print "Found these other possible distributions:\n";
    foreach my $otherSubdir (sort(keys(%foundOthers))) {
      print "'".$otherSubdir."'\n";
    }
  }

  exit 0;
}

if ($main::archiveOperation eq "refresh-archive") {
  # only rerelease single archive
  ($main::verbosity > 0) && print "PBA-Archiver running in forced refresh mode.\n";
  refreshDCGArchive($main::targetDCGArchive);

  ($main::verbosity > 0) && print "PBA-Archiver successfully refreshed archive ".$main::targetDCGArchive."\n";
  exit 0;
}


if ($main::archiveOperation eq "auto-import") {

  # check running builds || exit

  if (! -d "/var/run/pba-archiver") {
    ($main::verbosity > 0) && print "Auto-creating /var/run/pba-archiver\n";
    mkdir "/var/run/pba-archiver" || cleanupAndDie("FATAL: Cannot auto-create /var/run/pba-archiver\n");
  }
  chdir "/var/run/pba-archiver" || cleanupAndDie("FATAL: Cannot chdir to /var/run/pba-archiver\n");

  my @brotherPIDFiles = glob("*.pid");
  if (scalar(@brotherPIDFiles) > 0) {
    ($main::verbosity > 0) && print "PBA-Archiver refuses to disturb its ".scalar(@brotherPIDFiles)." already running brothers.\n";
    if ($main::verbosity > 1) {
      print "Those brothers have these PIDs:";
      foreach my $brotherPIDFile (@brotherPIDFiles) {
        my ($brotherPID, $ext) = split /\./, $brotherPIDFile, 2;
        print " ".$brotherPID;
      }
      print "\n";
    }
    exit 0;
  }
  
  my $pidFile = "/var/run/pba-archiver/".$$.".pid";
  printToFile( $pidFile, $$ );
  push @main::filesToCleanup, $pidFile;

  # begin normal scan-import-refresh run
  ($main::verbosity > 0) && print "PBA-Archiver running in auto-import (and refresh) mode.\n";

  scanForIncomingTargzFiles();

  if (scalar(@main::packageFilesToImport) == 0) {
    ($main::verbosity > 0) && print "PBA-Archiver OK: No new package files to import.\n";
    if  (-f $pidFile) { unlink $pidFile || cleanupAndDie("FATAL: Cannot /bin/rm ".$pidFile."\n"); }
    exit 0;
  }

  ($main::verbosity > 1) && print "Found ".scalar(@main::packageFilesToImport)." new package file(s) to import.\n";

  # for looping targz files
  my $workDir = "/var/spool/pba-archiver/work/".$$;
  push @main::dirsToCleanup, $workDir;
  mkdir $workDir || cleanupAndDie("FATAL: Cannot mkdir ".$workDir."\n");
  chdir $workDir || cleanupAndDie("FATAL: Cannot chdir ".$workDir."\n");

  # work new package files 

  my %touchedDCGArchivesByDCG = ();
  foreach my $packageFile (@main::packageFilesToImport) {
    ($main::verbosity > 2) && print "Working package file ".$packageFile."\n";
    # untar
    if ($main::verbosity > 2) { print "Un-taring ".$packageFile." in ".$workDir."\n"; }
    my $untarCmd = "tar -xzf ".$packageFile;
    executeOrDie($untarCmd);

    # find deb files 
    my @debFilesToImport = ();
    my $findCmd = "find ".$workDir." -mindepth 2 -maxdepth 2 -type f -name '*.deb'";
    #if ($main::verbosity > 2) { print $findCmd."\n"; }
    open (FINDOUTPUT, $findCmd."|") || cleanupAndDie("FATAL: Cannot search. Find command was:\n".$findCmd."\npwd was: ".pwd()."\n");
    while ( my $debFile = <FINDOUTPUT> ) {
      chomp $debFile;
      push @debFilesToImport, $debFile; 
    } 
    
    # work deb files
    foreach my $debFile (@debFilesToImport) {
      #($main::verbosity > 2) && print "Working deb file ".$debFile."\n";
      my $packageDCG = importDebFile($debFile);
      $touchedDCGArchivesByDCG{$packageDCG} = $packageDCG;
    }

    chdir "/var/run/pba-archiver/" || cleanupAndDie("FATAL: Cannot chdir /var/run/pba-archiver/\n");
    system "/bin/rm -rf ".$workDir;
    mkdir $workDir || cleanupAndDie("FATAL: Cannot re-mkdir ".$workDir."\n");
    chdir $workDir || cleanupAndDie("FATAL: Cannot chdir ".$workDir."\n");

    execute("/bin/rm -fv ".$packageFile);  
  }
  # system "/bin/rm -rf ".$workDir;
 
  foreach my $touchedDCGArchive (sort(keys(%touchedDCGArchivesByDCG))) {
    refreshDCGArchive( $touchedDCGArchive );
  }

  ($main::verbosity > 0) && print "PBA-Archiver successfully imported ".scalar(@main::packageFilesToImport)." new packages.\n";
  if  (-f $pidFile) { unlink $pidFile || cleanupAndDie("FATAL: Cannot /bin/rm ".$pidFile."\n"); }

  cleanup();
  exit 0;
}

cleanupAndDie("ERROR: pba-archiver called without a valid command\n");
exit 1;


