Archived
1
0
This repository has been archived on 2021-10-08. You can view files and clone it, but cannot push or open issues or pull requests.
ACU/ACU/VCS/Git.pm
Mercier Pierre-Olivier 8a4b545da6 chdir before remove dir
2013-11-06 18:13:08 +01:00

309 lines
6.4 KiB
Perl

#! /usr/bin/env perl
package Git;
use v5.10.1;
use strict;
use warnings;
use File::Path qw(remove_tree);
use File::Temp;
use ACU::LDAP;
use ACU::Log;
use ACU::API::Projects;
our $git_user = "git";
our $git_server;
our $git_adminrepo = "gitolite-admin.git";
our $configuration_directory = "/conf/";
our $configuration_file = "subjects.conf";
our $projects_directory = "subjects/";
my $gitolite_directory;
# General part
sub init_conf(;$)
{
$git_server = $_ if (shift);
$gitolite_directory = mktemp("/tmp/git_manage_XXXX");
log INFO, "Cloning $git_user\@$git_server:$git_adminrepo to $gitolite_directory";
qx(git clone $git_user\@$git_server:$git_adminrepo $gitolite_directory);
chdir($gitolite_directory);
return $gitolite_directory;
}
sub save_conf(;$)
{
chdir($gitolite_directory);
my $commit = shift;
qx(git commit -am '$commit') if ($commit);
log INFO, "Saving repositories configuration";
qx(git push);
chdir("/");
remove_tree($gitolite_directory);
$gitolite_directory = undef;
}
# Auth part: give to user right on repository
sub auth_add
{
my $rgroup = shift;
my $rname = shift;
my $accesss = shift;
init_conf() if (!$gitolite_directory);
say " repo $rname";
for my $access (@{ $accesss })
{
say $access->gen_string("gitolite");
#say " RW+ = \@admins \@$year-$project_name-$login";
#say " RW+ = \@chefs \@resp-$year-$project_name";
}
}
sub auth_update
{
init_conf() if (!$gitolite_directory);
}
sub auth_delete
{
init_conf() if (!$gitolite_directory);
}
sub auth_save
{
init_conf() if (!$gitolite_directory);
}
# Repository part: manage repositories
# Gitolite manage repositories only if there are associated with rights
sub repository_add
{
}
sub repository_update
{
}
sub repository_delete
{
}
sub repository_group_add
{
my $g_name = shift; #group_name
my $g_comp = shift; # complement, here respo rights
my $skip_save = shift // 0;
if ($g_name !~ /^[a-zA-Z-_.]+$/) {
log ERROR, "Group name ($g_name) does not respect expected format ; skip add.";
return 0;
}
init_conf() if (!$gitolite_directory);
if (-f $gitolite_directory.$configuration_directory.$projects_directory."/".$g_name.".conf") {
log ERROR, "Cannot add new repository group: $g_name already exists!";
return 0;
}
else {
open my $g_conf, ">", $gitolite_directory.$configuration_directory.$projects_directory."/".$g_name.".conf";
say $g_conf $g_conf;
close $g_conf;
open $g_conf, ">>", $gitolite_directory.$configuration_directory.$configuration_file;
say $g_conf "include \"$projects_directory/$g_name.conf\"";
close $g_conf;
}
save_conf("Add repositories group $g_name") unless($skip_save);
return 1;
}
sub repository_group_delete
{
my $g_name = shift; #group_name
my $skip_save = shift // 0;
if ($g_name !~ /^[a-zA-Z-_.]+$/) {
log ERROR, "Group name ($g_name) does not respect expected format ; skip add.";
return 0;
}
init_conf() if (!$gitolite_directory);
my $configuration_path = $gitolite_directory.$configuration_directory.$configuration_file;
if (-f $gitolite_directory.$configuration_directory.$projects_directory."/".$g_name.".conf") {
open my $g_conf, "<", $configuration_path;
my @contents = <$g_conf>;
close $g_conf;
@contents = grep !/^include "\Q$projects_directory\/$g_name.conf\E"$/, @contents; #";
open $g_conf, '>', $configuration_path or die $!;
print $g_conf @contents;
close $g_conf;
unlink($gitolite_directory.$configuration_directory.$projects_directory."/".$g_name.".conf");
}
else {
log WARN, "Repository group $g_name not found.";
return 0;
}
save_conf("Delete repositories group $g_name") unless($skip_save);
return 1;
}
sub repository_group_update
{
my $g_name = shift;
repository_group_delete($g_name, 1);
if (!repository_group_add($g_name, shift, 1)) {
log ERROR, "Unable to readd $g_name group repository. Configuration not saved.";
return 0;
}
# ...;
auth_add();
save_conf("Delete repositories group $g_name") unless(shift);
}
# User part: manage user authentication (password, keys, ...)
sub user_add
{
my $login = shift;
my $skip_save = shift // 0;
my $multiple = shift // 0;
if (!$login or $login !~ /^(\*|[a-zA-Z0-9._-]+)$/) {
log WARN, "Login required in user_add";
return 0;
}
init_conf() if (!$gitolite_directory);
# First, remove all user keys
user_delete($login, 1, $multiple);
# Then, extract user keys
my @entries = LDAP::search_dns(undef, "ou=users", "&(uid=$login)(sshPublicKey=*)", "uid", "sshPublicKey");
if ($#entries > 1 && !$multiple) { log WARN, "Found multiple user $login, aborting keys update."; return 0; }
for my $entry (@entries)
{
my $login = $entry->get_value("uid");
if ($login)
{
my $i = 0;
my @keys = $entry->get_value("sshPublicKey");
log INFO, "Updating ".($#keys+1)." keys for $login.";
for my $key (@keys)
{
chomp $key;
mkdir $gitolite_directory."/keydir/$i" unless (-d $gitolite_directory."/keydir/$i");
open my $kf, ">", $gitolite_directory."/keydir/$i/$login.pub";
print $kf $key;
close $kf;
qx(git add $gitolite_directory/keydir/$i/$login.pub);
$i += 1;
}
}
}
if ($multiple) {
save_conf("Update users keys from LDAP") unless ($skip_save);
}
else {
save_conf("Update $login keys from LDAP") unless ($skip_save);
}
return 1;
}
sub user_delete
{
my $login = shift;
my $skip_save = shift // 0;
my $multiple = shift // 0;
if (!$login) {
log WARN, "Login required in user_add";
return 0;
}
init_conf() if (!$gitolite_directory);
opendir(my $dh, "$gitolite_directory/keydir/") || die "can't opendir keydir: $!";
for my $f (readdir $dh)
{
if($multiple)
{
if ($f =~ /^[0-9]/ && -d "$gitolite_directory/keydir/$f") {
log INFO, "Removing $f directory";
remove_tree("$gitolite_directory/keydir/$f");
}
}
else
{
if (-f "$gitolite_directory/keydir/$f/$login.pub") {
log INFO, "Removing $f/$login.pub";
unlink("$gitolite_directory/keydir/$f/$login.pub");
}
}
}
closedir $dh;
save_conf("Remove $login keys") unless ($skip_save);
return 1;
}
sub user_update
{
return user_add(@_);
}
sub users_update
{
return user_add("*", (shift // 0), 1);
}
sub users_del
{
return user_del("*", (shift // 0), 1);
}
1;