#!/usr/bin/perl
#
# $Id$
#
# PBA builder main program
#
# (C) IBCL Informatik-Buero e.U. 2010
# (C) ITEG IT-Engineers GmbH 2015
#
# 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;

require "/usr/lib/pba/pba-functions.pl";
require "/usr/lib/pba/build-functions.pl";
require "/usr/lib/pba/debbuild-functions.pl";

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

prepareGetopts();

initPBAFunctions();

initBuildFunctions();

initDebBuildFunctions();

parseConfig();

checkBuildConfig();

checkDebBuildConfig();


if ($main::buildOperation =~ /^(enter|login)-pbabuilder$/) {
  ($main::verbosity > 0) && print "PBA-Builder running in ".$main::buildOperation." mode.\n";

  my $pbuilderCommand = "/usr/sbin/pbuilder login"; # was --login
  if ($main::pbabuilderArchitecture ne $main::targetArchitecture) {
    $pbuilderCommand .= " --host-arch ".$main::targetArchitecture;
  }
  my $pbuilderTgz = "/var/lib/pba-builder/pbuilder/".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.tgz";
  $pbuilderCommand .= " --basetgz ".$pbuilderTgz;
  if ($main::buildOperation eq "enter-pbabuilder") {
    ($main::verbosity > 0) && print "Using --save-after-login, changes will be saved back to tarball.\n";
    $pbuilderCommand .= " --save-after-login";
  } else {
    ($main::verbosity > 0) && print "Avoiding --save-after-login, no changes will be saved.\n";
  }
  #if ($main::configParams{"HttpProxy"} ne "") {
  #  $pbuilderCommand .= " --http-proxy ".$main::configParams{"HttpProxy"};
  #}

  ($main::verbosity > 0) && print "Executing this pbuilder command:\n".$pbuilderCommand."\n";
  dieIfNotRoot();
  executeOrDie($pbuilderCommand);

  ($main::verbosity > 0) && print "PBA-Builder has exited from ".$pbuilderTgz."\n";

  exit 0;
}


if ($main::buildOperation eq "create-pbabuilder") {
  ($main::verbosity > 0) && print "PBA-Builder running in create-pbabuilder mode.\n";

  my $pbuilderCommand = "/usr/sbin/pbuilder create"; # was --create
  if ($main::pbabuilderArchitecture ne $main::targetArchitecture) {
    $pbuilderCommand .= " --host-arch ".$main::targetArchitecture;
  }
  my $pbuilderTgz = "/var/lib/pba-builder/pbuilder/".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.tgz";
  $pbuilderCommand .= " --basetgz ".$pbuilderTgz;
  $pbuilderCommand .= " --mirror ".$main::distributionMirrors{$main::targetDistribution};
  $pbuilderCommand .= " --distribution ".$main::targetDistribution;
  $pbuilderCommand .= " --extrapackages apt-transport-https cdbs debhelper fakeroot";
  if ($main::configParams{"HttpProxy"} ne "") {
    $pbuilderCommand .= " --http-proxy ".$main::configParams{"HttpProxy"};
  }

  my $pbuilderLog = $main::logDir."/create-pbabuilder_".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.log";
  $pbuilderCommand .= " |tee ".$pbuilderLog." 2>&1";
  ($main::verbosity > 0) && print "Executing this pbuilder command:\n".$pbuilderCommand."\n";
  dieIfNotRoot();
  executeOrDie($pbuilderCommand);

  ($main::verbosity > 0) && print "PBA-Builder has successfully created ".$pbuilderTgz."\nSee ".$pbuilderLog."\n";

  exit 0;
}


if ($main::buildOperation eq "update-pbabuilder") {
  ($main::verbosity > 0) && print "PBA-Builder running in update-pbabuilder mode.\n";
  dieIfNotRoot();

  my $script = "#!/bin/sh\n";
  $script .= "export LANG=\"C\"\n";
  $script .= "/bin/rm /var/lib/apt/lists/*Packages* /var/lib/apt/lists/*Release* /var/lib/apt/lists/*Sources* >/dev/null 2>/dev/null\n";
  if ($main::configParams{"HttpProxy"} ne "") {
    $script .= "echo 'Acquire { http { Proxy \"".$main::configParams{"HttpProxy"}."\"; } }' >/etc/apt/apt.conf.d/999_proxy_http\n";
  }
  if ($main::configParams{"HttpSProxy"} ne "") {
    $script .= "echo 'Acquire { https { Proxy \"".$main::configParams{"HttpProxy"}."\"; } }' >/etc/apt/apt.conf.d/999_proxy_https\n";
  }
  $script .= "apt-get update && \\\n";
  $script .= "  apt-get -y upgrade && \\\n";
  $script .= "  apt-get -y dist-upgrade\n";
  $script .= 'FINALRC=$?'."\n";
  if ($main::configParams{"HttpProxy"} ne "") {
    $script .= "rm -f /etc/apt/apt.conf.d/999_proxy_http\n";
  }
  if ($main::configParams{"HttpSProxy"} ne "") {
    $script .= "rm -f /etc/apt/apt.conf.d/999_proxy_https\n";
  }
  $script .= 'exit $FINALRC'."\n";

  my $pbuilderTgz = "/var/lib/pba-builder/pbuilder/".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.tgz";
  my $pbuilderLog = "/var/log/pba-builder/update-pbabuilder_".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.log";

  if (executeInPbuilder( $script, $pbuilderTgz, $pbuilderLog, $main::targetArchitecture )) {
    print "PBA-Builder has successfully updated ".$pbuilderTgz."\nSee ".$pbuilderLog."\n";
  } else {
    cleanupAndDie("FATAL: Failed to update ".$pbuilderTgz."\nSee ".$pbuilderLog."\n");
  }
  
  exit 0;
}


if ($main::buildOperation eq "execute-in-pbabuilder") {
  ($main::verbosity > 0) && print "PBA-Builder running in execute-in-pbabuilder mode.\n";
  dieIfNotRoot();

  my $pbuilderTgz = "/var/lib/pba-builder/pbuilder/".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.tgz";
  my $pbuilderLog = "/var/log/pba-builder/execute-in-pbabuilder_".$main::targetDistribution."-".$main::targetArchitecture."-pba-base.log";

  if (executeInPbuilder( $main::scriptToExecute, $pbuilderTgz, $pbuilderLog, $main::targetArchitecture )) {
    print "PBA-Builder has successfully executed ".$main::scriptToExecute."\nin ".$pbuilderTgz."\nSee ".$pbuilderLog."\n";
  } else {
    cleanupAndDie("FATAL: Failed to execute ".$main::scriptToExecute."\nin ".$pbuilderTgz."\nSee ".$pbuilderLog."\n");
  }
  
  exit 0;
}

if ($main::buildOperation eq "auto-build-directory") {
  ($main::verbosity > 0) && print "PBA-Builder running in auto-build-directory mode, delegating to auto-build from ".$main::incomingDirs."\n";
  $main::buildOperation = "auto-build";
}

if ($main::buildOperation eq "auto-build") {
  ($main::verbosity > 0) && print "PBA-Builder running in auto-build mode.\n";
  dieIfNotRoot();


  # check running builds || exit

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

  my @brotherPIDFiles = glob("*.pid");
  if (scalar(@brotherPIDFiles) >= $main::maxParallelBuilds) {
    if ($main::ignoreMaxParallelBuilds > 0) {
      ($main::verbosity > 0) && print "WARNING: PBA-Builder will disturb (slow down) its ".scalar(@brotherPIDFiles)." already running brothers.\n";
    } else {
      ($main::verbosity > 0) && print "PBA-Builder 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";
    }
    if ($main::ignoreMaxParallelBuilds == 0) {
      cleanup();
      exit 0;
    }
  }
  
  my $pidFile = "/var/run/pba-builder/".$$.".pid";
  printToFile( $pidFile, $$ );
  push @main::filesToCleanup, $pidFile;

  # search new source package || exit

  scanForIncomingDscFiles();
  my $filesWorked = 0;

  while ($main::dscFileToBuild ne "") {

    ($main::verbosity > 1) && print "Selected a source package to build: ".$main::dscFileToBuild."\n";

    buildDscFile($main::dscFileToBuild);

    $filesWorked += 1;
    if ($filesWorked >= 8) {
      ($main::verbosity > 0) && print "Going to winter sleep after ".$filesWorked." finishing source packages files.\n";
      $main::dscFileToBuild = "";
    } else {
      scanForIncomingDscFiles();
    }
  }

  ($main::verbosity > 0) && print "PBA-Builder OK: No new source package to build.\n";
  if  (-f $pidFile) { unlink $pidFile || cleanupAndDie("FATAL: Cannot /bin/rm ".$pidFile."\n"); }
  cleanup();
  exit 0;
}


if ($main::buildOperation eq "test") {
  ($main::verbosity > 0) && print "PBA-Builder running in test mode.\n";

  #dieIfNotRoot();
  my $toNameAdresses = '"Christoph Lechleitner" <christoph.lechleitner@iteg.at>';

  my $ccNameAdresses = $main::buildReportsCc;
  $ccNameAdresses = "";

  my $subject = "Test-E-Mail from pba-functions.pl";

  my $message = "Testmessage\n\nblabla...\n\nkr\n";
  $subject = $message;
  $subject =~ s/\n.*//gm;

  my @filesToAttach = "";
  my $logfile = "/tmp/test1-".$$.".txt";
  printToFile ( $logfile, "test\nlog\nentries\n" );
  push @filesToAttach, $logfile;
  push @main::filesToCleanup, $logfile;

  my $logfile2 = "/tmp/test2-".$$.".log";
  printToFile ( $logfile2, "test2\nlog2\nentries2\n" );
  push @filesToAttach, $logfile2;
  push @main::filesToCleanup, $logfile2;

  my $logfile3 = "/tmp/test3-".$$.".log";
  printToFile ( $logfile3, "test3\nlog3\nentries3\n" );
  system ("bzip2 ".$logfile3);
  $logfile3 .= ".bz2";
  push @filesToAttach, $logfile3;
  push @main::filesToCleanup, $logfile3;

  sendEMail ( $main::buildReportsFrom, $toNameAdresses, $ccNameAdresses, $subject, $message, join(" ", @filesToAttach) );
  cleanup();
  
  exit 0;
}


print "PBA-Builder called without a valid command\n";
exit 1;

