Intégration de la branche add-repoctl

This commit is contained in:
Jephté Clain 2019-09-28 12:33:19 +04:00
commit de53bae548
6 changed files with 370 additions and 6 deletions

View File

@ -1,18 +1,21 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# Liste de préfixes permettant de taper le nom d'un dépôt plus rapidement e.g # Liste de préfixes permettant de taper le nom d'un dépôt plus rapidement e.g
# pcrone g/ssi-php/myproj # repoctl create g/ssi-php/myproj
# pcrone v:modules/myproj # repoctl create v:modules/myproj
# sont équivalents à # sont équivalents à
# pcrone https://git.univ-reunion.fr/ssi-php/myproj # repoctl create https://git.univ-reunion.fr/ssi-php/myproj
# pcrone git@vcs.univ.run:modules/myproj # repoctl create git@vcs.univ.run:modules/myproj
# Ces définitions fonctionnent aussi pour pclone
# Le format est ALIAS=ACTUAL # Le format est ALIAS=ACTUAL
#
# Ces définitions fonctionnent aussi pour tous les scripts qui utilisent
# repoctl, dont notamment pclone et pcrone
REPO_PREFIXES=( REPO_PREFIXES=(
s:=git@git.univ-reunion.fr: s:=git@git.univ-reunion.fr:
g/=https://git.univ-reunion.fr/ g/=https://git.univ-reunion.fr/
v:=git@vcs.univ.run: av/=https://vcs.univ-reunion.fr/anongit/ v:=git@vcs.univ.run: av/=https://vcs.univ-reunion.fr/anongit/
p:=pgit@vcs.univ.run: ap/=https://pvcs.univ-reunion.fr/anongit/ p:=pgit@vcs.univ.run: ap/=https://pvcs.univ-reunion.fr/anongit/
j/=https://git.jclain.fr/
) )
# Définitions des types de dépôt. Le format est NAME:TYPE:PREFIX # Définitions des types de dépôt. Le format est NAME:TYPE:PREFIX
@ -21,6 +24,7 @@ REPO_PREFIXES=(
# type par défaut est 'gitolite' # type par défaut est 'gitolite'
REPO_TYPES=( REPO_TYPES=(
ur:gitea:https://git.univ-reunion.fr/ ur:gitea:https://git.univ-reunion.fr/
jclain:gitea:https://git.jclain.fr/
) )
# Configuration de l'accès à l'API gogs # Configuration de l'accès à l'API gogs

27
lib/repoctl/json_build.php Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/php
<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
function fix_value($value) {
if ($value === "true") return true;
elseif ($value === "false") return false;
elseif ($value === "null") return null;
else return $value;
}
$data = array();
$empty = true;
for ($i = 1; $i < $argc; $i++) {
$namevalue = $argv[$i];
if (preg_match('/(.*?)=(.*)/', $namevalue, $ms)) {
$name = $ms[1];
$value = fix_value($ms[2]);
$data[$name] = $value;
} else {
$data[] = fix_value($namevalue);
}
$empty = false;
}
$options = JSON_NUMERIC_CHECK;
if ($empty) $options += JSON_FORCE_OBJECT;
echo json_encode($data, $options);

28
lib/repoctl/json_each.php Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/php
<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
if ($argc <= 1) die("ERROR: Vous devez spécifier le nom de la clé\n");
$data = json_decode(stream_get_contents(STDIN), true);
foreach ($data as $datum) {
$first = true;
for ($i = 1; $i < $argc; $i++) {
$result = $datum;
$keys = explode(".", trim($argv[$i]));
foreach ($keys as $key) {
if ($result === null) break;
if (!$key) continue;
if (isset($result[$key])) {
$result = $result[$key];
} else {
$result = null;
}
}
if ($first) $first = false;
else echo "\t";
if (is_array($result)) var_export($result);
else echo $result;
}
echo "\n";
}

27
lib/repoctl/json_get.php Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/php
<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
if ($argc <= 1) die("ERROR: Vous devez spécifier le nom de la clé\n");
$datum = json_decode(stream_get_contents(STDIN), true);
$first = true;
for ($i = 1; $i < $argc; $i++) {
$result = $datum;
$keys = explode(".", trim($argv[$i]));
foreach ($keys as $key) {
if ($result === null) break;
if (!$key) continue;
if (isset($result[$key])) {
$result = $result[$key];
} else {
$result = null;
}
}
if ($first) $first = false;
else echo "\t";
if (is_array($result)) var_export($result);
else echo $result;
}
echo "\n";

278
repoctl Executable file
View File

@ -0,0 +1,278 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS
function display_help() {
uecho "$scriptname: piloter un serveur git (gitolite, gogs, gitea, etc.)
USAGE
$scriptname ACTION URL [options]
ACTIONS
create URL [description]
Créer un nouveau dépôt avec la description spécifiée
list URL [VARs...]
Lister les dépôts dans l'organisation spécifiée. Si aucune organisation
n'est spécifiée dans l'url, lister les dépôts *accessibles* par
l'utilisateur (cela inclut les dépôts des organisations auxquelles
l'utilisateur a accès)
VARs est une liste de variables à afficher pour chaque dépôt, séparés
par le caractère tabulation. La valeur par défaut est full_name
delete URL
Supprimer le dépôt spécifié"
# pas encore possible d'implémenter pour le moment:
#move URL ORG[/NAME]
# Déplacer le dépôt spécifié dans l'organisation spécifiée. Le cas
# échéant, le dépôt est renommé
}
function json_build() {
"$scriptdir/lib/repoctl/json_build.php" "$@"
}
function json_get() {
"$scriptdir/lib/repoctl/json_get.php" "$@"
}
function json_each() {
"$scriptdir/lib/repoctl/json_each.php" "$@"
}
function repoctl_init() {
repourl="${1%.git}"
[ -n "$repourl" ] || return
rname=
rtype=gitolite
rprefix=
REPO_PREFIXES=()
REPO_TYPES=()
set_defaults repoctl
# Traduire les aliases éventuels
local asrcdest asrc adest
for asrcdest in "${REPO_PREFIXES[@]}"; do
splitfsep "$asrcdest" = asrc adest
if [ "${repourl#$asrc}" != "$repourl" ]; then
newurl="$adest${repourl#$asrc}"
if [ "$newurl" != "$repourl" ]; then
enote "$repourl --> $newurl"
repourl="$newurl"
break
fi
fi
done
local rnametypeprefix tmp found
for rnametypeprefix in "${REPO_TYPES[@]}"; do
splitfsep "$rnametypeprefix" : rname tmp
splitfsep "$tmp" : rtype rprefix
if [ "${repourl#$rprefix}" != "$repourl" ]; then
found=1
break
fi
done
if [ -z "$found" ]; then
rname=
rtype=gitolite
rprefix=
fi
}
function curlto() {
local url="$1"; shift
local payload="$1"; shift
local outfile="$1"; shift
local tmpfile
if [ -z "$outfile" ]; then
ac_set_tmpfile tmpfile
outfile="$tmpfile"
fi
local -a args
local r http_code
args=(-s -w '%{http_code}' -o "$outfile")
[ -n "$payload" ] && args+=(-d "$payload")
[ -n "$HTTP_METHOD" ] && args+=(-X "$HTTP_METHOD")
args+=("$@" "$url")
setx http_code=curl "${args[@]}"
case "$http_code" in
2*) r=0;;
4*) r=1;;
5*) r=3;;
*) r=11;;
esac
if [ -n "$tmpfile" ]; then
cat "$tmpfile"
ac_clean "$tmpfile"
fi
upvar http_code "$http_code"
return "$r"
}
function gogs_setvars() {
gogs_url="${rname}_GOGS_URL"; gogs_url="${!gogs_url}"
gogs_user="${rname}_GOGS_USER"; gogs_user="${!gogs_user}"
gogs_key="${rname}_GOGS_KEY"; gogs_key="${!gogs_key}"
userpath="${repourl#$rprefix}"
splitfsep "$userpath" / user path
}
################################################################################
function create_action() {
case "$rtype" in
#gitolite) ;;
gogs|gitea)
gogs_setvars
gogs_create_action "$@"
;;
*) die "$rtype: type de dépôt non supporté";;
esac
}
function gogs_create_action() {
local url desc payload result
local -a vars
if [ -n "$user" -a "$user" != "$gogs_user" ]; then
# lister les dépôts d'une organisation
url="$gogs_url/api/v1/orgs/$user/repos"
else
# lister les dépôts accessibles par l'utilisateur
url="$gogs_url/api/v1/user/repos"
fi
vars=(name="$path" private=true)
[ -n "$1" ] && vars+=(description="$1"); shift
setx payload=json_build "${vars[@]}"
[ $# -gt 0 ] && vars=("$@") || vars=("")
setx result=curlto "$url" "$payload" "" \
-H 'Content-Type: application/json' \
-H "Authorization: token $gogs_key" || \
die "Une erreur s'est produite lors de la tentative de création du dépôt
url: $url
payload: $payload
result: $result"
echo "$result" | json_get "${vars[@]}"
}
################################################################################
function list_action() {
case "$rtype" in
#gitolite) ;;
gogs|gitea)
gogs_setvars
gogs_list_action "$@"
;;
*) die "$rtype: type de dépôt non supporté";;
esac
}
function gogs_list_action() {
local url result
local -a vars
if [ -n "$user" -a "$user" != "$gogs_user" ]; then
# lister les dépôts d'une organisation
url="$gogs_url/api/v1/orgs/$user/repos"
else
# lister les dépôts accessibles par l'utilisateur
url="$gogs_url/api/v1/user/repos"
fi
[ $# -gt 0 ] && vars=("$@") || vars=(full_name)
setx result=curlto "$url" "" "" \
-H 'Content-Type: application/json' \
-H "Authorization: token $gogs_key" || \
die "Une erreur s'est produite lors de la tentative de listage des dépôts
url: $url
result: $result"
echo "$result" | json_each "${vars[@]}"
}
################################################################################
#XXX à implémenter. ça ne semble pas encore possible pour le moment. peut-être
# uniquement le renommage?!
function move_action() {
case "$rtype" in
#gitolite) ;;
gogs|gitea)
gogs_setvars
gogs_move_action "$@"
;;
*) die "$rtype: type de dépôt non supporté";;
esac
}
function gogs_move_action() {
local url payload result
local -a vars
setx payload=json_build name="$new_name"
url="$gogs_url/api/v1/repos/$user/$path"
local HTTP_METHOD=PATCH
[ $# -gt 0 ] && vars=("$@") || vars=("")
setx result=curlto "$url" "$payload" "" \
-H 'Content-Type: application/json' \
-H "Authorization: token $gogs_key" || \
die "Une erreur s'est produite lors de la tentative de déplacement du dépôt
url: $url
payload: $payload
result: $result"
echo "$result" | json_get "${vars[@]}"
}
################################################################################
function delete_action() {
case "$rtype" in
#gitolite) ;;
gogs|gitea)
gogs_setvars
gogs_delete_action "$@"
;;
*) die "$rtype: type de dépôt non supporté";;
esac
}
function gogs_delete_action() {
local url payload result
setx payload=json_build owner="$user" repo="$path"
url="$gogs_url/api/v1/repos/$user/$path"
local HTTP_METHOD=DELETE
setx result=curlto "$url" "$payload" "" \
-H 'Content-Type: application/json' \
-H "Authorization: token $gogs_key" || \
die "Une erreur s'est produite lors de la tentative de suppression du dépôt
url: $url
payload: $payload
result: $result"
if [ -n "$result" ]; then
echo "$result"
fi
}
################################################################################
action=
args=(
--help '$exit_with display_help'
-c,--create action=create
-l,--list action=list
#-m,--move action=move
-d,--delete action=delete
)
parse_args "$@"; set -- "${args[@]}"
if [ -z "$action" ]; then
action="$1"; shift
fi
[ -n "$action" ] || action=list
repoctl_init "$1"; shift
[ -n "$repourl" ] || die "Vous devez spécifier l'url du dépôt"
case "$action" in
c|create) create_action "$@";;
l|list) list_action "$@";;
#m|move) move_action "$@";;
d|del|delete|rm|remove) delete_action "$@";;
esac

View File

@ -250,7 +250,7 @@ function cxone_init() {
REPO_PREFIXES=() REPO_PREFIXES=()
REPO_TYPES=() REPO_TYPES=()
set_defaults pcrone set_defaults repoctl
# Traduire les aliases éventuels # Traduire les aliases éventuels
local asrcdest asrc adest local asrcdest asrc adest