576 lines
12 KiB
Perl
Executable File
576 lines
12 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
use v5.10;
|
|
use Digest::SHA qw(sha1_base64);
|
|
use File::Basename;
|
|
|
|
use ACU::API::Projects;
|
|
use ACU::Defense;
|
|
use ACU::LDAP;
|
|
use ACU::Log;
|
|
$ACU::Log::log_file = "/var/log/hooks/" . basename($0) . ".log";
|
|
use ACU::Process;
|
|
|
|
# First, check if the repository is in the subjects/ directory
|
|
exit 0 if ($ENV{GL_REPO} !~ /^subjects\//);
|
|
|
|
my ($ref, $oldsha, $newsha) = @ARGV;
|
|
|
|
log WARN, "This is a subject!";
|
|
|
|
my %known_tags = (
|
|
"defense" => \&tag_defense,
|
|
"grades" => \&tag_grades,
|
|
"project" => \&tag_project,
|
|
"subject" => \&tag_document,
|
|
"ref" => \&tag_ref,
|
|
"tests" => \&tag_tests,
|
|
);
|
|
|
|
if ($ref =~ m<^refs/tags(/.+)$>)
|
|
{
|
|
my $tag = $1;
|
|
my @args;
|
|
|
|
while ($tag =~ m<[,/]([^,]+)>g) {
|
|
push @args, $1;
|
|
}
|
|
|
|
my $create = ($newsha ne '0' x 40);
|
|
|
|
if (exists $known_tags{$args[0]}) {
|
|
exit $known_tags{$args[0]}($create, @args);
|
|
}
|
|
}
|
|
|
|
exit 0;
|
|
|
|
sub check_xml
|
|
{
|
|
my $content = shift;
|
|
my $dtd = shift;
|
|
|
|
my $fh;
|
|
if ($dtd) {
|
|
open $fh, "|xmllint --noout --dtdvalid $dtd -";
|
|
}
|
|
else {
|
|
open $fh, "|xmllint --noout -";
|
|
}
|
|
print $fh ${ $content };
|
|
close $fh;
|
|
|
|
return $?;
|
|
}
|
|
|
|
sub repository_name
|
|
{
|
|
my $repo = $ENV{GL_REPO};
|
|
$repo =~ s#^subjects/(.*)#$1#;
|
|
return $repo;
|
|
}
|
|
|
|
|
|
sub tag_defense
|
|
{
|
|
my $creation = shift;
|
|
|
|
# From here, we have:
|
|
# 0: "defense"
|
|
# 1: $version
|
|
# 2: $id
|
|
# 3: $path
|
|
# 4: $year
|
|
|
|
my $version = $_[1] // 1;
|
|
|
|
my $project_id = repository_name();
|
|
if ($_[2]) {
|
|
$project_id .= "-" . $_[2];
|
|
}
|
|
$project_id = lc $project_id;
|
|
$project_id =~ s/[^a-z0-9-_]/_/g;
|
|
|
|
my $path;
|
|
if ($_[3])
|
|
{
|
|
if ($_[3] =~ /(?:defenses\/)?([a-zA-Z0-9\/]+)(?:.xml)/) {
|
|
$path = "defenses/".$1.".xml";
|
|
} else {
|
|
$path = $_[3];
|
|
}
|
|
}
|
|
else {
|
|
# Looking for an uniq defense file in defenses/
|
|
$path = qx(git ls-tree -r --name-only $ARGV[2] defenses/ | egrep '\.xml\$');
|
|
my $nb_defenses = $path =~ tr/\n//;
|
|
if ($nb_defenses > 1) {
|
|
log ERROR, "Veuillez préciser le chemin de la soutenance à utiliser avec un tag : defense,$_[1],$_[2],file_to_use";
|
|
exit 1;
|
|
}
|
|
elsif ($nb_defenses == 0) {
|
|
log ERROR, "Aucune soutenance n'a été trouvée dans le dossier defenses/";
|
|
exit 1;
|
|
}
|
|
chomp($path);
|
|
}
|
|
|
|
my $defense_id;
|
|
if ($path =~ /(?:defenses\/)?([a-zA-Z0-9\/]+)(?:.xml)/) {
|
|
$defense_id = $1;
|
|
} else {
|
|
log ERROR, "Déplacez votre soutenance dans le dossier defenses ou simplifiez le nom du fichier.";
|
|
}
|
|
|
|
my $year;
|
|
if ($_[4])
|
|
{
|
|
# Check on year
|
|
if ($_[4] !~ /^\d+$/) {
|
|
log ERROR, "project:*:* second argument is the year. Tag format: project:id:year";
|
|
}
|
|
|
|
$year = $_[4];
|
|
}
|
|
else {
|
|
$year = LDAP::get_year;
|
|
}
|
|
|
|
# Determine full tag
|
|
my $long_tag;
|
|
{
|
|
my $proj_id = $_[2] // "";
|
|
$long_tag = "defense,$version,$proj_id,$path,$year";
|
|
}
|
|
|
|
if ($creation)
|
|
{
|
|
my $newref = $ARGV[2];
|
|
|
|
log INFO, "Looking for $path...";
|
|
# Check file exists
|
|
my $content = qx(git show $newref:$path);
|
|
if ($?) {
|
|
log ERROR, "Impossible de trouver la soutenance.";
|
|
}
|
|
|
|
# Check DTD validity
|
|
if (check_xml(\$content, "http://acu.epita.fr/dtd/defense.dtd")) {
|
|
log ERROR, "Corrigez les erreurs du fichier $path avant de publier la soutenance.";
|
|
}
|
|
|
|
# TODO: check user permissions
|
|
|
|
# TODO: check presence in project.xml
|
|
|
|
# Generate questions and answer id
|
|
my $defense = Defense->new(\$content);
|
|
$defense->genIds();
|
|
|
|
# Send data to intradata
|
|
log INFO, "Attente d'un processus de publication...";
|
|
if (my $err = Process::Client::launch("intradata_get", { action => "update", type => "defense", id => $project_id, "year" => $year, "defense_id" => $defense_id, "version" => $version }, { "$defense_id.xml" => $defense->toString() }))
|
|
{
|
|
if (${ $err } ne "Ok") {
|
|
log ERROR, "Erreur durant le processus de publication : " . ${ $err };
|
|
}
|
|
}
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -f $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long créé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Is the long tag existing
|
|
qx(git tag | egrep "^$long_tag\$");
|
|
if ($?) {
|
|
log ERROR, "Tag long correspondant introuvable : $long_tag.";
|
|
}
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -d $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long supprimé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub tag_document
|
|
{
|
|
|
|
}
|
|
|
|
sub tag_grades
|
|
{
|
|
my $creation = shift;
|
|
|
|
# From here, we have:
|
|
# 1: "defense"
|
|
# 2: $version
|
|
# 3: $id
|
|
# 4: $year
|
|
|
|
my $version = $_[2] // 1;
|
|
|
|
my $project_id = repository_name();
|
|
if ($_[3]) {
|
|
$project_id .= "-" . $_[3];
|
|
}
|
|
$project_id = lc $project_id;
|
|
$project_id =~ s/[^a-z0-9-_]/_/g;
|
|
|
|
my $year;
|
|
if ($_[4]) {
|
|
# Check on year
|
|
if ($_[4] !~ /^\d+$/) {
|
|
log ERROR, "grades,*,*,* second argument is the year. Tag format: grades,version,id,year";
|
|
}
|
|
|
|
$year = $_[4];
|
|
}
|
|
else {
|
|
$year = LDAP::get_year;
|
|
}
|
|
|
|
# Determine full tag
|
|
my $long_tag;
|
|
{
|
|
my $proj_id = $_[3] // "";
|
|
$long_tag = "grades,$version,$proj_id,$year";
|
|
}
|
|
|
|
if ($creation)
|
|
{
|
|
my $newref = $ARGV[2];
|
|
|
|
# Check file exists
|
|
my $content = qx(git show $newref:grades/grades.xml);
|
|
if ($?) {
|
|
log ERROR, "Impossible de trouver le fichier de notation.";
|
|
}
|
|
|
|
# Check DTD validity
|
|
if (check_xml(\$content, "http://acu.epita.fr/dtd/grading.dtd")) {
|
|
log ERROR, "Corrigez les erreurs du fichier grades.xml avant de lancer la génération des notes.";
|
|
}
|
|
|
|
# TODO: check user permissions
|
|
|
|
# Send data to intradata
|
|
log INFO, "Attente d'un processus de publication...";
|
|
Process::Client::launch("intradata_get", { action => "generate", type => "grades", id => $project_id, "year" => $year, "version" => $version }, { "grading.xml" => $content }, 1);
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -f $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long créé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Is the long tag existing
|
|
qx(git tag | egrep "^$long_tag\$");
|
|
if ($?) {
|
|
log ERROR, "Tag long correspondant introuvable : $long_tag.";
|
|
}
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -d $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long supprimé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub tag_project
|
|
{
|
|
my $creation = shift;
|
|
|
|
# From here, we have:
|
|
# 1: "project"
|
|
# 2: $id
|
|
# 3: $year
|
|
|
|
my $project_id = repository_name();
|
|
if ($_[2]) {
|
|
|
|
# Check on ID/flavour_id
|
|
if ($_[2] =~ /^\d+$/) {
|
|
log ERROR, "project:* tag can't take version. Tag format: project:id:year";
|
|
}
|
|
|
|
$project_id .= "-" . $_[2];
|
|
}
|
|
$project_id = lc $project_id;
|
|
$project_id =~ s/[^a-z0-9-_]/_/g;
|
|
|
|
my $year;
|
|
if ($_[3]) {
|
|
# Check on year
|
|
if ($_[3] !~ /^\d+$/) {
|
|
log ERROR, "project:*:* second argument is the year. Tag format: project:id:year";
|
|
}
|
|
|
|
$year = $_[3];
|
|
}
|
|
else {
|
|
$year = LDAP::get_year;
|
|
}
|
|
|
|
# Determine full tag
|
|
my $long_tag;
|
|
if (!$_[3])
|
|
{
|
|
my $proj_id = $_[2] // "";
|
|
$long_tag = "project,$proj_id,$year";
|
|
}
|
|
|
|
if ($creation)
|
|
{
|
|
my $newref = $ARGV[2];
|
|
|
|
my $content = qx(git show $newref:project.xml);
|
|
# Check file exists
|
|
if ($?) {
|
|
log ERROR, "Créez un fichier project.xml à la racine du dépôt.";
|
|
}
|
|
|
|
# Check DTD validity
|
|
if (check_xml(\$content, "http://acu.epita.fr/dtd/project.dtd")) {
|
|
log ERROR, "Corrigez les erreurs du fichier project.xml avant de lancer la création du projet.";
|
|
}
|
|
|
|
# TODO: check user permissions
|
|
|
|
# Project already online?
|
|
my $project;
|
|
eval {
|
|
$project = API::Project::get($project_id, $year);
|
|
};
|
|
|
|
if ($project) {
|
|
log INFO, "Mise à jour du projet $project_id";
|
|
}
|
|
else {
|
|
log INFO, "Création du projet $project_id";
|
|
}
|
|
|
|
# Generate token for VCS submission
|
|
my $dom = XML::LibXML->load_xml(string => (\$content));
|
|
my $mod = 0;
|
|
for my $vcs ($dom->documentElement()->getElementsByTagName("vcs"))
|
|
{
|
|
if (! $vcs->hasAttribute("token"))
|
|
{
|
|
if ($project)
|
|
{
|
|
# Looking for an old token
|
|
my @rendus = grep {
|
|
exists $_->{vcs} and $_->{vcs}{tag} eq $vcs->hasAttribute("tag");
|
|
} @{ $project->{submissions} };
|
|
|
|
if (@rendus == 1) {
|
|
log INFO, "Use existing token: ".$rendus[0]->{vcs}{token};
|
|
$vcs->setAttribute("token", substr($rendus[0]->{vcs}{token}, 2, 23));
|
|
$mod = 1;
|
|
next;
|
|
}
|
|
}
|
|
|
|
my $token;
|
|
do {
|
|
$token = sha1_base64(rand);
|
|
$token =~ s/[^a-zA-Z0-9]//g;
|
|
} while (length $token < 12);
|
|
$vcs->setAttribute("token", substr($token, 2, 23));
|
|
$mod = 1;
|
|
}
|
|
}
|
|
|
|
if ($mod) {
|
|
$content = $dom->toString();
|
|
}
|
|
|
|
# Send data to intradata
|
|
log INFO, "Attente d'un processus de publication...";
|
|
if (my $err = Process::Client::launch("intradata_get", { action => "update", type => "project", id => $project_id, "year" => $year }, { "butler.xml" => $content }))
|
|
{
|
|
if (${ $err } ne "Ok") {
|
|
log ERROR, "Erreur durant le processus de publication : " . ${ $err };
|
|
}
|
|
}
|
|
|
|
log INFO, "Information de l'intranet...";
|
|
# Call API
|
|
eval {
|
|
API::Projects::add($project_id, $year);
|
|
};
|
|
if ($@)
|
|
{
|
|
my $err = $@;
|
|
if ($err =~ /[pP]roject [aA]ll?ready [eE]xists/) {
|
|
log WARN, $err;
|
|
}
|
|
else {
|
|
log ERROR, $err;
|
|
}
|
|
}
|
|
|
|
log DONE, "Projet créé/mis à jour avec succès.";
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -f $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long créé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Is the long tag existing
|
|
qx(git tag | egrep "^$long_tag\$");
|
|
if ($?) {
|
|
log ERROR, "Tag long correspondant introuvable : $long_tag.";
|
|
}
|
|
|
|
log USAGE, "Suppression du projet !";
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -d $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long supprimé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub tag_ref
|
|
{
|
|
my $creation = shift;
|
|
|
|
# From here, we have:
|
|
# 1: "ref"
|
|
# 2: $id
|
|
# 3: rendu-X
|
|
# 4: $year
|
|
|
|
my $project_id = repository_name();
|
|
if ($_[2]) {
|
|
|
|
# Check on ID/flavour_id
|
|
if ($_[2] =~ /^\d+$/) {
|
|
log ERROR, "ref,* tag can't take version. Tag format: ref,id,rendu,year";
|
|
}
|
|
|
|
$project_id .= "-" . $_[2];
|
|
}
|
|
$project_id = lc $project_id;
|
|
$project_id =~ s/[^a-z0-9-_]/_/g;
|
|
|
|
my $rendu;
|
|
if ($_[3]) {
|
|
$rendu = $_[3];
|
|
}
|
|
else {
|
|
$rendu = "*";
|
|
}
|
|
|
|
my $year;
|
|
if ($_[4]) {
|
|
# Check on year
|
|
if ($_[4] !~ /^\d+$/) {
|
|
log ERROR, "ref,*,*,* third argument is the year. Tag format: ref,id,rendu,year";
|
|
}
|
|
|
|
$year = $_[4];
|
|
}
|
|
else {
|
|
$year = LDAP::get_year;
|
|
}
|
|
|
|
# Determine full tag
|
|
my $long_tag;
|
|
{
|
|
my $proj_id = $_[2] // "";
|
|
$long_tag = "ref,$proj_id,$rendu,$year";
|
|
}
|
|
|
|
if ($creation)
|
|
{
|
|
my $newref = $ARGV[2];
|
|
|
|
log INFO, "Création/mise à jour de la ref...";
|
|
|
|
my $content = qx(git show $newref:ref/Makefile);
|
|
# Check file exists
|
|
if ($?) {
|
|
log ERROR, "Un fichier Makefile est requis pour pouvoir compiler et exécuter la ref.";
|
|
}
|
|
|
|
log INFO, "Création de la tarball...";
|
|
|
|
my $archive = qx(git archive --format=tgz $newref ref/);
|
|
|
|
# Send data to moulette
|
|
log INFO, "Attente d'un processus de compilation...";
|
|
if (my $err = Process::Client::launch("moulette_get", {
|
|
type => "ref",
|
|
id => $project_id,
|
|
"year" => $year,
|
|
"rendu" => $rendu,
|
|
"file" => "ref_$rendu.tgz"
|
|
}, { "ref_$rendu.tgz" => $archive }))
|
|
{
|
|
if (${ $err } ne "Ok") {
|
|
log ERROR, "Erreur durant le processus de compilation : " . ${ $err };
|
|
}
|
|
}
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -f $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long créé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Is the long tag existing
|
|
qx(git tag | egrep "^$long_tag\$");
|
|
if ($?) {
|
|
log ERROR, "Tag long correspondant introuvable : $long_tag.";
|
|
}
|
|
|
|
log USAGE, "Suppression du projet !";
|
|
|
|
if ($long_tag)
|
|
{
|
|
qx(git tag -d $long_tag);
|
|
if (! $?) {
|
|
log INFO, "Tag long supprimé : $long_tag.";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub tag_tests
|
|
{
|
|
|
|
}
|