<commit_before># $Id$
# $Source$
# $Author$
# $HeadURL$
# $Revision$
# $Date$
package Arepa::Web::App;

use strict;
use warnings;
our $VERSION = 0.10;
use 5.00800;

use Carp    qw(carp croak); # NEVER USE warn OR die !
use English qw(-no_match_vars);
use File::Basename;
use File::Copy;

use base qw(CGI::Application);
use CGI::Application::Plugin::TT;
use CGI::Application::Plugin::Authentication;
use CGI::Application::Plugin::Session;
use YAML;
use Data::Dumper;

use Parse::Debian::PackageDesc;
use Arepa::Config;
use Arepa::Repository;
use Arepa::BuilderFarm;

my @conffiles = qw(/etc/arepa/config.yml);
our $config      = undef;
our $config_path = undef;
foreach my $conffile (@conffiles) {
    if (-r $conffile) {
        $config_path = $conffile;
        $config = Arepa::Config->new($config_path);
        last ;
    }
}

# This is a sub for CGI::Application authentication module
sub validate_username_password {
    my ($user, $password) = @_;
    my %users = %{YAML::LoadFile($config->get_key('web_ui:user_file'))};
    return ($users{$user} eq $password);
}

sub setup {
    my ($self) = @_;

    $self->authen->config(
        DRIVER => [ 'Generic', \&validate_username_password ],
        LOGOUT_RUNMODE => 'logout',
    );
    $self->session_config(CGI_SESSION_OPTIONS => ["driver:File",
                                                  $self->query,
                                                  {Directory=>'/tmp'}],
                          DEFAULT_EXPIRY => '+1w',
                          COOKIE_PARAMS  => {-expires => '+24h', -path => '/'},
                          SEND_COOKIE    => 1);
    $self->authen->protected_runmodes(':all');
    $self->authen->protected_runmodes('logout');
    $self->start_mode('home');
    $self->mode_param('rm');
    $self->run_modes(
            'home'        => 'home',
            'approve'     => 'approve',
            'approve_all' => 'approve_all',
            'build_log'   => 'show_build_log',
            'requeue'     => 'requeue',
            'logout'      => 'logout',
    );
    $self->tt_include_path($config->get_key('web_ui:template_dir'));

    $self->{error_list} = [];
}

sub show_view {
    my ($self, $template, $stash) = @_;

    $self->tt_process($template, { $self->base_stash,
                                   %$stash });
}

sub base_stash {
    my ($self) = @_;
    (base_url     => $config->get_key('web_ui:base_url'),
     cgi_base_url => $config->get_key('web_ui:cgi_base_url'));
}

sub add_error {
    my ($self, $error, $output) = @_;
    push @{$self->{error_list}}, {error  => $error,
                                  output => $output};
}

sub error_list {
    my ($self) = @_;
    @{$self->{error_list}};
}

sub last_cmd_output {
    my ($self) = @_;
    $self->{last_cmd_output};
}

sub home {
    my ($self) = @_;

    my @packages = ();
    if (opendir D, $config->get_key('upload_queue:path')) {
        @packages = grep /\.changes$/, readdir D;
        closedir D;
    }

    # Packages pending approval ----------------------------------------------
    my (@readable_packages, @unreadable_packages);
    my $gpg_dir = $config->get_key('web_ui:gpg_homedir');
    foreach my $package (@packages) {
        my $package_path = $config->get_key('upload_queue:path')."/".$package;
        my $obj = undef;
        eval {
            $obj = Parse::Debian::PackageDesc->new($package_path,
                                                   gpg_homedir => $gpg_dir);
        };
        if ($obj) {
            push @readable_packages, $obj;
        }
        else {
            push @unreadable_packages, $package;
        }
    }

    # Compilation queue ------------------------------------------------------
    my $packagedb = Arepa::PackageDb->new($config->get_key('package_db'));
    my @compilation_queue = $packagedb->
                                get_compilation_queue(status => 'pending',
                                                      limit  => 10);
    my @pending_compilations = ();
    foreach my $comp (@compilation_queue) {
        my %source_pkg_attrs =
            $packagedb->get_source_package_by_id($comp->{source_package_id});
        push @pending_compilations, {
            %$comp,
            package => { %source_pkg_attrs },
        };
    }

    # Builder status ---------------------------------------------------------
    # Get the builder information and find out which package is being compiled
    # by each builder, if any
    my @builder_list = ();
    my @compiling_packages = $packagedb->
                                get_compilation_queue(status => 'compiling',
                                                      limit  => 10);
    foreach my $builder_name ($config->get_builders) {
        my %extra_attrs = (status => 'idle');
        foreach my $pkg (@compiling_packages) {
            if ($pkg->{builder} eq $builder_name) {
                my %source_pkg_attrs = $packagedb->get_source_package_by_id($pkg->{source_package_id});
                $extra_attrs{status}  = 'compiling';
                $extra_attrs{package} = { %source_pkg_attrs };
                $extra_attrs{since}   = $pkg->{compilation_started_at};
            }
        }
        push @builder_list,
             { $config->get_builder_config($builder_name),
               %extra_attrs };
    }

    # Latest compilation failures --------------------------------------------
    my @failed_compilations = ();
    my @failed_compilation_queue = $packagedb->
                        get_compilation_queue(status => 'compilationfailed',
                                              limit  => 10);
    foreach my $comp (@failed_compilation_queue) {
        my %source_pkg_attrs =
            $packagedb->get_source_package_by_id($comp->{source_package_id});
        push @failed_compilations, {
            %$comp,
            package => { %source_pkg_attrs },
        };
    }

    # Latest compiled packages -----------------------------------------------
    my @latest_compilations = ();
    my @latest_compilation_queue = $packagedb->
                        get_compilation_queue(status => 'compiled',
                                              limit  => 10);
    foreach my $comp (@latest_compilation_queue) {
        my %source_pkg_attrs =<commit_msg>* Fix "Latest xxx" listings so they're really the latest and not the first<commit_after># $Id$
# $Source$
# $Author$
# $HeadURL$
# $Revision$
# $Date$
package Arepa::Web::App;

use strict;
use warnings;
our $VERSION = 0.10;
use 5.00800;

use Carp    qw(carp croak); # NEVER USE warn OR die !
use English qw(-no_match_vars);
use File::Basename;
use File::Copy;

use base qw(CGI::Application);
use CGI::Application::Plugin::TT;
use CGI::Application::Plugin::Authentication;
use CGI::Application::Plugin::Session;
use YAML;
use Data::Dumper;

use Parse::Debian::PackageDesc;
use Arepa::Config;
use Arepa::Repository;
use Arepa::BuilderFarm;

my @conffiles = qw(/etc/arepa/config.yml);
our $config      = undef;
our $config_path = undef;
foreach my $conffile (@conffiles) {
    if (-r $conffile) {
        $config_path = $conffile;
        $config = Arepa::Config->new($config_path);
        last ;
    }
}

# This is a sub for CGI::Application authentication module
sub validate_username_password {
    my ($user, $password) = @_;
    my %users = %{YAML::LoadFile($config->get_key('web_ui:user_file'))};
    return ($users{$user} eq $password);
}

sub setup {
    my ($self) = @_;

    $self->authen->config(
        DRIVER => [ 'Generic', \&validate_username_password ],
        LOGOUT_RUNMODE => 'logout',
    );
    $self->session_config(CGI_SESSION_OPTIONS => ["driver:File",
                                                  $self->query,
                                                  {Directory=>'/tmp'}],
                          DEFAULT_EXPIRY => '+1w',
                          COOKIE_PARAMS  => {-expires => '+24h', -path => '/'},
                          SEND_COOKIE    => 1);
    $self->authen->protected_runmodes(':all');
    $self->authen->protected_runmodes('logout');
    $self->start_mode('home');
    $self->mode_param('rm');
    $self->run_modes(
            'home'        => 'home',
            'approve'     => 'approve',
            'approve_all' => 'approve_all',
            'build_log'   => 'show_build_log',
            'requeue'     => 'requeue',
            'logout'      => 'logout',
    );
    $self->tt_include_path($config->get_key('web_ui:template_dir'));

    $self->{error_list} = [];
}

sub show_view {
    my ($self, $template, $stash) = @_;

    $self->tt_process($template, { $self->base_stash,
                                   %$stash });
}

sub base_stash {
    my ($self) = @_;
    (base_url     => $config->get_key('web_ui:base_url'),
     cgi_base_url => $config->get_key('web_ui:cgi_base_url'));
}

sub add_error {
    my ($self, $error, $output) = @_;
    push @{$self->{error_list}}, {error  => $error,
                                  output => $output};
}

sub error_list {
    my ($self) = @_;
    @{$self->{error_list}};
}

sub last_cmd_output {
    my ($self) = @_;
    $self->{last_cmd_output};
}

sub home {
    my ($self) = @_;

    my @packages = ();
    if (opendir D, $config->get_key('upload_queue:path')) {
        @packages = grep /\.changes$/, readdir D;
        closedir D;
    }

    # Packages pending approval ----------------------------------------------
    my (@readable_packages, @unreadable_packages);
    my $gpg_dir = $config->get_key('web_ui:gpg_homedir');
    foreach my $package (@packages) {
        my $package_path = $config->get_key('upload_queue:path')."/".$package;
        my $obj = undef;
        eval {
            $obj = Parse::Debian::PackageDesc->new($package_path,
                                                   gpg_homedir => $gpg_dir);
        };
        if ($obj) {
            push @readable_packages, $obj;
        }
        else {
            push @unreadable_packages, $package;
        }
    }

    # Compilation queue ------------------------------------------------------
    my $packagedb = Arepa::PackageDb->new($config->get_key('package_db'));
    my @compilation_queue = $packagedb->
                                get_compilation_queue(status => 'pending',
                                                      limit  => 10);
    my @pending_compilations = ();
    foreach my $comp (@compilation_queue) {
        my %source_pkg_attrs =
            $packagedb->get_source_package_by_id($comp->{source_package_id});
        push @pending_compilations, {
            %$comp,
            package => { %source_pkg_attrs },
        };
    }

    # Builder status ---------------------------------------------------------
    # Get the builder information and find out which package is being compiled
    # by each builder, if any
    my @builder_list = ();
    my @compiling_packages = $packagedb->
                                get_compilation_queue(status => 'compiling',
                                                      limit  => 10);
    foreach my $builder_name ($config->get_builders) {
        my %extra_attrs = (status => 'idle');
        foreach my $pkg (@compiling_packages) {
            if ($pkg->{builder} eq $builder_name) {
                my %source_pkg_attrs = $packagedb->get_source_package_by_id($pkg->{source_package_id});
                $extra_attrs{status}  = 'compiling';
                $extra_attrs{package} = { %source_pkg_attrs };
                $extra_attrs{since}   = $pkg->{compilation_started_at};
            }
        }
        push @builder_list,
             { $config->get_builder_config($builder_name),
               %extra_attrs };
    }

    # Latest compilation failures --------------------------------------------
    my @failed_compilations = ();
    my @failed_compilation_queue = $packagedb->
                        get_compilation_queue(status => 'compilationfailed',
                                              order  => "compilation_requested_at DESC",
                                              limit  => 10);
    foreach my $comp (@failed_compilation_queue) {
        my %source_pkg_attrs =
            $packagedb->get_source_package_by_id($comp->{source_package_id});
        push @failed_compilations, {
            %$comp,
            package => { %source_pkg_attrs },
        };
    }

    # Latest compiled packages -----------------------------------------------
    my @latest_compilations = ();
    my @latest_compilation_queue = $packagedb->
                        get_compilation_queue(status => 'compiled',
                                              order  => "compilation_requested_at DESC",
                                              limit  => 10);
    foreach my $comp (@latest_compilation_queue) {
        my %source_pkg_attrs =
{'fraction_non_alphanumeric': 0.1740148263753414, 'fraction_numerical': 0.003277409285992977, 'mean_word_length': 1.7848761408083442, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 153, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1416968', 'n_tokens_mistral': 3853, 'n_tokens_neox': 3723, 'n_words': 721}