Intégration de la branche release-9.4.1

This commit is contained in:
Jephté Clain 2020-01-20 14:46:16 +04:00
commit 1210ca7382
24 changed files with 2306 additions and 222 deletions

View File

@ -1,3 +1,67 @@
## Version 9.4.1 du 20/01/2020-14:46
* `6f01bac` dk: si la commande est inconnue, la transmettre à docker
* `175f6ed` cssh: traiter le cas où screen n'est pas disponible
* `73db728` umail: possibilité de spécifier le type de body
* `5fc55cc` dk: support des fonctions de nettoyage par profil
* `21274af` dk: APPS peut avoir une valeur dépendante du profil
* `f7f8889` support des filtres avec wildcards
* `747c563` repoctl: divers bugs
* `4fdd23c` dk: support limité de podman
* `5457228` dk: support des aliases pour les mappings pff
* `a55f9c4` dk: ajout de get-profile
* `ac7efad` dk: possibilité de forcer la suppression des images
* `5284838` typo
* `d5c5162` dk: dans build.env, une variable peut en mentionner une autre
* `f7d036a` repoctl: cosmetic
* `87b8d5b` Intégration de la branche update-repoctl
* `0866bbd` finaliser edit et implémenter get
* `8daf4ec` début implémentation edit
* `ef1c8f2` utiliser dk composer, et ne pas utiliser de container par défaut
* `269379f` dk: rendre le code overridable
* `aae3703` bug avec traitement des variables de docker-machine -u
* `f875093` dk: par défaut, forcer l'utilisation de la machine locale pour dk composer
* `c202a27` dk: support COMPOSER_SETUP et COMPOSER_CMD
* `921caa1` dk: le shell est lancé en root
* `ce98445` dk: support de composer shell
* `2b5ed18` dk: ajouter un frontend pour composer
* `29c54e7` dmctl: import/export de docker machines
* `de53bae` Intégration de la branche add-repoctl
* `600b824` support limité de pcrone et pclone
* `914f635` implémentation initiale de create, list, delete
* `a774497` squelette
* `5a444a6` dk: support pff
* `425e8a5` dk: maj format ps
* `52c3d7a` dk: ps, ls et rm prennent des filtres. ajout de pull
* `d5f8fa4` cx-updatedev: ajout de l'option -g
* `5fe5137` dk: support de COMPOSER_ACTION et sqlmig NOFIX
* `74cf35b` typo
* `0468623` alias pour docer-machine
* `3dfe542` dk: support de scripts génériques
* `488a257` délai pour éviter les maj intempestives d'eclipse
* `13ce5b8` dk: tagger aussi avec la distribution
* `d03b04f` dk: ajouter automatiquement le suffixe -$DIST à la version
* `6879491` maj doc
* `7fad363` cssh: compat avec les vieilles versionsd de linux
* `f65dda6` bug
* `bc7eebc` ajouter --with-registry-auth à dk update
* `8af50f4` nettoyage de logs webobjects
* `458ccd3` dk: support de certaines options pour dk run
* `c97bc6a` dk: support de la commande run
* `ae70f66` synchro des dépendances uniquement pour le type composer
* `f508dae` support des mises à jour en mode devel
* `60a4c73` cx-conndev: ajouter l'option -d
* `85ac283` cx-conndev: renommer l'option en --mysql-cmd
* `80db462` cx-conndev: ajout de l'option --cmd
* `4400ba7` ajout de ensure-vip
* `ae7ffeb` cx-updatedev: remplacer --ru par -w, --ud, --ur en fonction des besoins
* `9bfd515` dk -c est auto-complete friendly
* `a5a41d9` dk: support de fichiers compose non défaut
* `7e5859e` bug
* `b342960` bug
* `c44d1d3` dk: par défaut, ne pas ajouter le profil au nom de projet
* `aa4eb4a` cx-updatedev: ajout des mises à jour récursives
## Version 9.4.0 du 05/06/2019-10:15
* `fb96852` Intégration de la branche dk-deploy

View File

@ -1 +1 @@
9.4.0
9.4.1

13
cssh
View File

@ -32,9 +32,22 @@ function __ask() {
}
function __auto_screen() {
# Si screen pas installé, ne rien faire
if [ -z "$(which screen 2>/dev/null)" ]; then
echo "'"$COULEUR_JAUNE"'WARNING'"$COULEUR_NORMALE"' screen introuvable. une session bash classique sera lancée"
exec /bin/bash -l
fi
# Si on est déjà dans screen, ne rien faire
[ -z "$STY" ] || return
# corriger TERM pour les vieilles versions de Linux
case "$TERM" in
xterm*) TERM=xterm;;
screen*) TERM=screen;;
esac
export TERM
local msgprefix
local screens count

View File

@ -8,16 +8,34 @@ function display_help() {
USAGE
$scriptname [DATABASE]
$scriptname -c|-d [-uUSER [-pPASSWORD]] ...
OPTIONS
-h, -s, --service SERVICE
Spécifier le nom du service. La valeur par défaut est db"
Spécifier le nom du service. La valeur par défaut est db
-c, --mysql-cmd
Lancer 'mysql -hSERVICE_IP' avec les arguments supplémentaires fournis
sur la ligne de commande
-d, --mysqldump-cmd
Lancer 'mysqldump --databases --add-drop-database -hSERVICE_IP' avec
les arguments supplémentaires fournis sur la ligne de commande
-u, --user USER
-p, --password PASSWORD
Paramètres supplémentaires utilisés uniquement avec les options -c et -d"
}
service=db
mysql_cmd=
mysqldump_cmd=
user=
password=
args=(
--help '$exit_with display_help'
-h:,-s:,--service: service=
-c,--mysql-cmd mysql_cmd=1
-d,--mysqldump-cmd mysqldump_cmd=1
-u:,--user: user=
-p:,--password: password=
)
parse_args "$@"; set -- "${args[@]}"
@ -44,7 +62,7 @@ fi
###
function die_not_found() { die "$service: service introuvable"; }
function die_not_found() { die "$service: service introuvable. vérifiez que le projet est actuellement up"; }
setx cid=docker-compose ps -q "$service" 2>/dev/null || die_not_found
[ -n "$cid" ] || die_not_found
edebug "$service id: $cid"
@ -54,7 +72,15 @@ setx ip=docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{en
[ -n "$ip" ] || die_not_found
edebug "$service ip: $ip"
mysqlcmd="$(php bin/conndev.php "$ip" "$@")"
edebug "mysqlcmd: $mysqlcmd"
if [ -n "$mysql_cmd" ]; then
mysql -h"$ip" ${user:+-u"$user"} ${password:+-p"$password"} "$@"
eval "$mysqlcmd"
elif [ -n "$mysqldump_cmd" ]; then
mysqldump --databases --add-drop-database -h"$ip" ${user:+-u"$user"} ${password:+-p"$password"} "$@"
else
mysql_cmd="$(php bin/conndev.php "$ip" "$@")"
edebug "mysql_cmd: $mysql_cmd"
eval "$mysql_cmd"
fi

View File

@ -17,34 +17,75 @@ OPTIONS
Afficher simplement ce qui serait fait
-q, --quiet
Ne pas lancer rsync en mode verbose
-g, --no-wait
Ne pas attendre avant de faire git commit
--rsync
Mettre à jour les répertoires dans vendor/ qui ne sont pas des liens
symboliques à partir des projets dépendants correspondants. Les liens
symboliques créés avec --link sont ignorés. C'est l'option par défaut.
-l, --link
Transformer les clones de dépôts en liens directs vers les projets
Transformer les clones de dépôts dans vendor/ en liens symboliques vers
les projets dépendants correpondants.
-k, --copy
Transformer les liens directs vers les projets en copies des projets
Transformer les liens symboliques dans vendor/ en copies des projets
dépendants correspondants. Les répertoires qui ne sont pas des liens
symboliques sont ignorés.
Cette option peut être considérée comme le contraire de --link
-i, --install
Supprimer les répertoires et les faire recréer par composer i
Supprimer les répertoires des projets dépendants dans vendor/, qu'il
s'agisse de liens symboliques ou de répertoires normaux, puis les faire
recréer par 'composer i'
Celà permet de ramener le projet à l'état original.
-j, --reinstall-link
Supprimer les répertoires et les faire recréer par composer i,
uniquement s'il s'agit de liens
Supprimer les répertoires des projets dépendants dans vendor/ s'il
s'agit de liens symboliques, puis les faire recréer par 'composer i'
Cette variante est plus rapide que --install puisqu'on ne cherche pas à
tout recréer.
-u, --update
Supprimer les répertoires et les faire recréer par composer u"
Supprimer les répertoires des projets dépendants dans vendor/, qu'il
s'agisse de liens symboliques ou de répertoires normaux, puis les faire
recréer par 'composer u'
Celà permet de mettre à jour le projet sans les erreurs qui résultent
des modifications faites par les autres actions.
-w, --update-commit
Mettre à jour le projet avec --update puis enregistrer les modifications
éventuelles dans git
--ud, --update-deps
Mettre à jour les projets dépendants avec --update-commit avant de
mettre à jour le projet courant.
--ur, --update-recursive
Mettre à jour de façon récursive tous les projets dépendants.
NB: les modifications dans les projets dépendants seront automatiquement
enregistrées dans git."
}
fake=
verbose=1
action=
nowait=
action=rsync
args=(
--help '$exit_with display_help'
-d:,--project-dir: projdir=
-n,--fake fake=1
-q,--quiet verbose=
-g,--no-wait nowait=1
-l,--link action=link
-k,--copy action=copy
-i,--install action=install
-j,--reinstall-link action=reinstall-link
-u,--update action=update
-w,--update-commit action=update-commit
--ud,--update-deps action=update-deps
--ur,--update-recursive action=update-recursive
)
parse_args "$@"; set -- "${args[@]}"
if [ -d "$projdir" ]; then
cd "$projdir"
elif [ -e "$projdir" ]; then
die "$projdir: répertoire introuvable"
fi
found=
first=1
while true; do
@ -62,11 +103,11 @@ if [ -z "$first" ]; then
enote "Le répertoire du projet est $(ppath . ~)"
fi
case "$action" in
install|update)
[ -x ./composer.phar ] || die "Impossible de trouver composer.phar"
;;
esac
if [ "$action" == update-deps -o "$action" == update-recursive ]; then
# avec update-deps et update-recursive, tous les modules doivent être
# considérés
set --
fi
###
@ -91,6 +132,7 @@ function update_with_rsync() {
}
deps=()
modules=()
for m in "$@"; do
m="${m#vendor/}" # pour permettre de spécifier le chemin directement
m="${m//\//-}"
@ -98,10 +140,19 @@ for m in "$@"; do
ur-*|lib-*) ;;
*) m="ur-$m";;
esac
modules+=("$m")
p="${m//-/\/}"
check_module
case "$action" in
rsync)
# Action par défaut: ignorer les liens et synchroniser les copies
if [ ! -L "vendor/$p" ]; then
etitle "$m"
update_with_rsync
eend
fi
;;
link)
# Ignorer les liens et transformer les copies en liens
if [ ! -L "vendor/$p" ]; then
@ -153,7 +204,7 @@ for m in "$@"; do
array_add deps "$p"
eend
;;
update)
update|update-commit|update-deps|update-recursive)
# Supprimer les liens et répertoires...
etitle "$m"
if [ -e "vendor/$p" ]; then
@ -163,28 +214,70 @@ for m in "$@"; do
array_add deps "$p"
eend
;;
*)
# Action par défaut: ignorer les liens et synchroniser les copies
if [ ! -L "vendor/$p" ]; then
etitle "$m"
update_with_rsync
eend
fi
;;
*) die "$action: action inconnue";;
esac
done
case "$action" in
install|reinstall-link)
# ... puis installer les dépendances
etitle "Installation des dépendances"
./composer.phar i
eend
estep "Installation des dépendances"
"$scriptdir/dk" ci || die
;;
update)
update|update-commit)
# ... puis mettre à jour les dépendances
etitle "Mise à jour des dépendances"
./composer.phar u "${deps[@]}"
eend
estep "Mise à jour des dépendances"
"$scriptdir/dk" cu "${deps[@]}" || die
if [ "$action" == update-commit ]; then
if [ -z "$nowait" ]; then
# laisser le temps à @$*! d'eclipse qui met à jour automatiquement le projet...
estep "Attendre 10 secondes avant git commit"
sleep 10
fi
estep "Enregistrement dans git"
pci -A "maj deps"
fi
;;
update-deps)
# mettre à jour les dépendances directes
for m in "${modules[@]}"; do
etitle "Mise à jour projet dépendant: $m"
"$script" -d "../$m" -w
eend
done
estep "Mise à jour des dépendances"
"$scriptdir/dk" cu || die
if [ -z "$nowait" ]; then
# laisser le temps à @$*! d'eclipse qui met à jour automatiquement le projet...
estep "Attendre 10 secondes avant git commit"
sleep 10
fi
estep "Enregistrement dans git"
pci -A "maj deps"
;;
update-recursive)
# mettre à jour les dépendances de façon récursive
for m in "${modules[@]}"; do
etitle "Mise à jour récursive: $m"
"$script" -d "../$m" --ur
eend
done
estep "Mise à jour des dépendances"
"$scriptdir/dk" cu || die
if [ -z "$nowait" ]; then
# laisser le temps à @$*! d'eclipse qui met à jour automatiquement le projet...
estep "Attendre 10 secondes avant git commit"
sleep 10
fi
estep "Enregistrement dans git"
pci -A "maj deps"
;;
esac

1053
dk

File diff suppressed because it is too large Load Diff

116
dmctl Executable file
View File

@ -0,0 +1,116 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source /etc/ulibauto || exit 1
function display_help() {
uecho "$scriptname: import/exporter une docker-machine
USAGE
$scriptname -d NAME
$scriptname -l ARCHIVE
OPTIONS
-d, --dump
Exporter la machine
-l, --load
Import la machine"
}
action=
args=(
--help '$exit_with display_help'
-d,--dump,-x,--export,-s,--save action=dump
-l,--load,-i,--import action=load
)
parse_args "$@"; set -- "${args[@]}"
if [ -z "$action" ]; then
case "$1" in
d|dump|x|export|s|save) action=dump; shift;;
l|load|i|import) action=load; shift;;
*) die "Vous devez spécifier l'action à effectuer";;
esac
fi
case "$action" in
dump)
############################################################################
name="$1"
[ -n "$name" ] || die "Vous devez spécifier le nom de la machine"
srcdir="$HOME/.docker/machine/machines/$name"
[ -d "$srcdir" ] || die "$name: nom de machine incorrect"
ac_set_tmpdir workdir
destdir="$workdir/$name"
archive="${name}-machine.tar.gz"
estep "Copie des fichiers"
cp -r "$srcdir" "$workdir" || die
for i in ca-key.pem ca.pem key.pem cert.pem; do
[ -f "$destdir/$i" ] || {
cp "$HOME/.docker/machine/certs/$i" "$destdir" || die
}
done
estep "Correction des chemins"
sed -i "\
s|$HOME/.docker/machine|DOCKER_MACHINE_HOME|g
s|DOCKER_MACHINE_HOME/certs/|DOCKER_MACHINE_HOME/machines/$name/|g
" "$destdir/config.json" || die
estep "Génération de $archive"
tar czf "$archive" -C "$workdir" "$name" || die
ac_clean "$workdir"
;;
load)
############################################################################
archive="$1"
[ -n "$archive" ] || die "Vous devez spécifier l'archive à importer"
setx archivename=basename -- "$archive"
if [[ "$archivename" == *-machine.tar.gz ]]; then
name="${archivename%-machine.tar.gz}"
else
die "$archive: n'est pas une archive docker-machine"
fi
destdir="$HOME/.docker/machine/machines"
machinedir="$destdir/$name"
origdir="$HOME/${name}-machine.orig"
if [ -d "$machinedir" ]; then
ewarn "$name: une machine du même nom existe déjà"
ask_yesno "Voulez-vous l'écraser?" N || die
[ -d "$origdir" ] && rm -rf "$origdir"
mv "$machinedir" "$origdir"
fi
ac_set_tmpdir workdir
srcdir="$workdir/$name"
estep "Extraction de l'archive"
tar xzf "$archive" -C "$workdir"
[ -d "$srcdir" ] || die "L'archive n'est pas pour la machine $name"
estep "Corriger les chemins"
sed -i "\
s|DOCKER_MACHINE_HOME|$HOME/.docker/machine|g
" "$srcdir/config.json" || die
estep "Installation de la machine"
mkdir -p "$destdir"
mv "$srcdir" "$destdir"
if [ -d "$origdir" ]; then
enote "Une fois que la machine aura été testée, vous pouvez supprimer ce répertoire:
$origdir"
fi
ac_clean "$workdir"
;;
esac

122
ensure-vip Executable file
View File

@ -0,0 +1,122 @@
#!/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 ipcalc
function display_help() {
uecho "$scriptname: s'assurer que l'hôte courant a l'adresse IP spécifiée
USAGE
$scriptname IPs...
NB: ce script ne supporte que la modification d'interfaces qui ne sont pas des
bridges. il est conçu avant tout pour utilisation sur un serveur, pas un poste
de travail.
OPTIONS
-i, --ignore-iface IFACE
Ajouter une interface à la liste des interfaces à ignorer. Si cette
option est utilisée, la liste par défaut n'est pas utilisée, sauf si
l'option -d est utilisée aussi.
-d, --defaults
Ajouter les valeurs suivantes à liste des interfaces à ignorer:
${DEFAULT_IGNORE_IFACES[*]}
Cette option est automatiquement activée si l'option -i n'est pas
utilisée
-n, --fake
Afficher simplement les modification à effectuer"
}
DEFAULT_IGNORE_IFACES=(
"docker*"
"br-*"
"veth*"
)
DEFAULT_PROFILES=(prod test devel)
ignore_ifaces=()
fake=
args=(
--help '$exit_with display_help'
-i:,--ignore-iface: ignore_ifaces
-d,--defaults '$array_extend ignore_ifaces DEFAULT_IGNORE_IFACES'
-n,--fake fake=1
)
parse_args "$@"; set -- "${args[@]}"
require_debian
for vip in "$@"; do
[ "${vip%/*}" != "$vip" ] || vip="$vip/32"
vips+=("$vip")
done
array_fix_paths ignore_ifaces
[ ${#ignore_ifaces[*]} -gt 0 ] || ignore_ifaces=("${DEFAULT_IGNORE_IFACES[@]}")
if [ -n "$fake" ]; then
set_verbosity --debug
__NETWORK_DEVEL_SHOW_MODIFS=1
__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS=1
fi
################################################################################
# réimplémentation "corrigée" de network_config_partial()
nifile="$__DEBIAN_NETWORK_INTERFACES"
network_set_confips
network_set_confbrs
tmpconfips=()
for confip in "${confips[@]}"; do
network_parse_confip "$confip" iface gateway ipsuffixes
continue=
for ignore_iface in "${ignore_ifaces[@]}"; do
if eval "[[ \"\$iface\" == $(qwc "$ignore_iface") ]]"; then
continue=1
break
fi
done
[ -n "$continue" ] && continue
tmpconfips+=("$confip")
network_parse_ipsuffix "${ipsuffixes[0]}" mainip suffix
for vip in "${vips[@]}"; do
if [ "${vip%.*}" == "${mainip%.*}" ]; then
tmpconfips+=("$iface:$vip")
fi
done
done
confips=("${tmpconfips[@]}")
confbrs=()
network_fix_confs
network_config "" confips confbrs || exit 0
# des modifications ont eu lieu, tenter de configurer les nouvelles adresses
# d'abord calculer les adresses ips qui sont activées
network_set_confips
for confip in "${confips[@]}"; do
network_parse_confip "$confip" iface gateway ipsuffixes
for ipsuffix in "${ipsuffixes[@]}"; do
network_parse_ipsuffix "$ipsuffix" ip suffix
array_addu ips "$ip"
done
done
# puis lister les commandes correspondant aux adresses ips non activées
array_from_lines ups "$(awkrun <"$nifile" -f ips[@] '
$1 == "up" && $2 == "ip" && $3 == "addr" && $4 == "add" {
ip = $5; sub(/(\/[0-9.]+)?$/, "", ip) # enlever suffixe
if (! in_array(ip, ips)) {
$1 = ""
print
}
}')"
if [ ${#ups[*]} -gt 0 ]; then
etitle "Configuration des nouvelles adresses"
for up in "${ups[@]}"; do
estep "$up"
eval "$up"
done
eend
fi

View File

@ -87,7 +87,7 @@ OPTIONS
-C, --composer-projects
Equivalent à '--ptitle -p */composer.json --'
--cc, --composer-cmd
Equivalent à '--ptitle -p */composer.phar -- ./composer.phar'"
Equivalent à '--ptitle -p */composer.json -- dk composer'"
}
basedir=
@ -129,7 +129,7 @@ composer)
[ "$title" == auto ] && title=p
;;
composer-cmd)
set -- */composer.phar -- ./composer.phar "$@"
set -- */composer.json -- "$scriptdir/dk" composer "$@"
parentdir=1
[ "$title" == auto ] && title=p
;;

View File

@ -0,0 +1,13 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
if [ -n "$UTOOLS_DOCKER_ALIASES" ]; then
if [ "$DOCKER_MACHINE_WRAPPED" == true ]; then
alias dm=__docker_machine_wrapper
else
alias dm=docker-machine
fi
if [ -n "$UTOOLS_BASH_COMPLETION" ]; then
complete -F _docker_machine dm
fi
fi

View File

@ -14,3 +14,6 @@
# _root. Par défaut, ce n'est le cas que si sudo n'est pas installé. Si sudo est
# configuré, il est préférable de ne pas utiliser su.
#export UTOOLS_USES_SU=false
# Activer les aliases pour l'utilisation de docker
#export UTOOLS_DOCKER_ALIASES=1

View File

@ -5,3 +5,6 @@
# Profiles pour docker-machine
#DM_PROFILES=(name:profile...)
# Image à utiliser pour lancer composer
#COMPOSER_IMAGE=docker.univ-reunion.fr/image/utils-icmycas-php-apache:d9

View File

@ -1,18 +1,21 @@
# -*- 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
# pcrone g/ssi-php/myproj
# pcrone v:modules/myproj
# repoctl create g/ssi-php/myproj
# repoctl create v:modules/myproj
# sont équivalents à
# pcrone https://git.univ-reunion.fr/ssi-php/myproj
# pcrone git@vcs.univ.run:modules/myproj
# Ces définitions fonctionnent aussi pour pclone
# repoctl create https://git.univ-reunion.fr/ssi-php/myproj
# repoctl create git@vcs.univ.run:modules/myproj
# Le format est ALIAS=ACTUAL
#
# Ces définitions fonctionnent aussi pour tous les scripts qui utilisent
# repoctl, dont notamment pclone et pcrone
REPO_PREFIXES=(
s:=git@git.univ-reunion.fr:
g/=https://git.univ-reunion.fr/
v:=git@vcs.univ.run: av/=https://vcs.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
@ -21,6 +24,7 @@ REPO_PREFIXES=(
# type par défaut est 'gitolite'
REPO_TYPES=(
ur:gitea:https://git.univ-reunion.fr/
jclain:gitea:https://git.jclain.fr/
)
# Configuration de l'accès à l'API gogs

View File

@ -77,6 +77,7 @@ def run_umail():
('a:', 'attach=', "Attacher un fichier"),
('t:', 'content-type=', "Spécifier le type de contenu du fichier"),
('f:', 'body=', "Spécifier un fichier contenant le corps du message"),
(None, 'html', "Indiquer que le corps du message est du type text/html. Par défaut, il s'agit de text/plain"),
(None, 'gencmd', "Générer une commande à évaluer pour envoyer le mail"),
])
options, args = get_args(None, options, longoptions)
@ -87,6 +88,7 @@ def run_umail():
mbccs = []
body = None
bodyfile = None
bodymtype = 'plain'
afiles = []
amimetypes = []
gencmd = False
@ -110,6 +112,8 @@ def run_umail():
bodyfile = None
elif not path.exists(bodyfile):
die("%s: fichier introuvable" % bodyfile)
elif option in ('--html',):
bodymtype = 'html'
elif option in ('--gencmd',):
gencmd = True
@ -133,14 +137,14 @@ def run_umail():
if not afiles:
# Sans attachement, faire un message simple
msg = MIMEText('\n'.join(lines), 'plain')
msg = MIMEText('\n'.join(lines), bodymtype)
msg.set_charset('utf-8')
else:
# Il y a des attachement, faire un multipart
msg = MIMEMultipart()
#msg.set_charset('utf-8')
if lines:
body = MIMEText('\n'.join(lines), 'plain')
body = MIMEText('\n'.join(lines), bodymtype)
body.set_charset('utf-8')
msg.attach(body)
i = 0

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

@ -0,0 +1,48 @@
#!/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;
}
function setp(&$array, $keys, $value) {
if (is_array($keys)) $keys = implode(".", $keys);
$keys = explode(".", $keys);
$last = count($keys) - 1;
$i = 0;
if ($array === null) $array = array();
$current =& $array;
foreach ($keys as $key) {
if ($i == $last) break;
if (!array_key_exists($key, $current)) $current[$key] = array();
if (!is_array($current[$key])) $current[$key] = array($current[$key]);
$current =& $current[$key];
$i++;
}
if ($key === "") {
$current[] = $value;
} else {
$current[$key] = $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]);
setp($data, $name, $value);
} else {
$value = fix_value($namevalue);
$data[] = $value;
}
$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";

301
lib/ulib/pff Normal file
View File

@ -0,0 +1,301 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
urequire multiconf
PFF_ORIGEXT=pff
PFF_CONF=.pff.conf # ne pas modifier
DEFAULT_PFF_ORIGEXTS=(".$ORIGEXT" .origine .default)
DEFAULT_PFF_PROTECTS=(/.git/ .svn/ /pff/ "/$PFF_CONF")
PFF_CONFVARS=(
"VERSION//Version actuellement installée"
-a
"PVERSIONS//Versions en attente d'intégration"
"PROFILES//Profils définis"
-s
"DISTTYPE=auto//Type de distribution upstream: full ou patch"
-a
"ORIGEXTS=//Extensions origines"
"PROTECTS=//Fichiers locaux à protéger lors de l'intégration e.g /dir/, /file, etc."
"MKDIRS//Répertoires qui doivent toujours exister"
"FILTERS//Filtres appliqués aux fichiers lors de l'intégration"
"NOMERGES=//Fichiers qu'il ne faut pas chercher à fusionner"
)
# Nomenclature pour le nommage des fichiers traités:
# pfile: le chemin absolu du fichier dans le projet
# rfile: le chemin relatif du fichier dans le projet
# bfile: le chemin absolu du fichier dans pff/Base/
# Cfile: le chemin absolu du fichier dans pff/Common/
# cfile: le chemin absolu du fichier dans pff/Current/
# Pfile: le chemin absolu du fichier dans pff/ANYPROFILE/
# plink: la destination du lien pfile
# clink: la destination du lien cfile
# Plink: la destination du lien Pfile
function flexists() {
[ -e "$1" -o -L "$1" ]
}
function multiups() {
# afficher un chemin vers le haut e.g ../../.. avec autant d'éléments que
# les répertoires du chemin relatif $1.
# méthode: commencer avec la valeur de départ $2 et préfixer avec autant de
# ../ que nécessaire. puis afficher le résultat.
local tmp="$1" link="$2"
setx tmp=dirname -- "$tmp"
while [ "$tmp" != . ]; do
[ -n "$link" ] && link="/$link"
link="..$link"
setx tmp=dirname -- "$tmp"
done
echo "$link"
}
function find_pffdir() {
# trouver le répertoire du projet pff à partir du répertoire $2(=.) et
# mettre le chemin absolu dans la variable $1(=pffdir)
# si le répertoire n'est pas trouvé, retourner 1
local destvar="${1:-pffdir}" pffdir
setx pffdir=abspath "${2:-.}"
while true; do
if [ -f "$pffdir/$PFF_CONF" -a -d "$pffdir/pff" ]; then
local "$destvar"
upvar "$destvar" "$pffdir"
return 0
fi
[ "$pffdir" == / -o "$pffdir" == "$HOME" ] && break
setx pffdir=dirname -- "$pffdir"
done
return 1
}
function ensure_pffdir() {
# trouver le répertoire du projet pff à partir du répertoire $2(=.) et
# mettre le chemin absolu dans la variable $1(=pffdir)
# si le répertoire n'est pas trouvé, arrêter le script avec un code d'erreur
local destvar="${1:-pffdir}" pffdir
if find_pffdir pffdir "$2"; then
conf_init "${PFF_CONFVARS[@]}"
source "$pffdir/$PFF_CONF"
local "$destvar"; upvar "$destvar" "$pffdir"
return
fi
local msg="Projet pff introuvable (utiliser --init ?)"
[ -n "$2" ] && die "$2: $msg" || die "$msg"
}
function pff_get_current_profile() {
# afficher le profil courant du projet pff $1, s'il est défini
local pffdir="$1"
[ -L "$pffdir/pff/.Current" ] && readlink "$pffdir/pff/.Current"
}
function pff_get_profiles() {
# afficher tous les profils valides du projet pff $1
local pffdir="$1"
(for profile in "${PROFILES[@]}"; do echo "$profile"; done
list_dirs "$pffdir/pff") | sort -u | grep -vxF Current
}
function pff_get_user_profiles() {
# afficher tous les profils modifiables du projet pff $1 (c'est à dire tous
# les profils valides excepté Base)
pff_get_profiles "$@" | grep -vxF Base
}
function pff_get_first_profile() {
# afficher le premier profil autre que Base du projet pff $1
local profile
profile="${PROFILES[0]}"
if [ -z "$profile" -o "$profile" == Base ]; then
pff_get_user_profiles "$@" | head -n1
else
echo "$profile"
fi
}
function pff_get_local_files() {
# afficher tous les fichiers locaux exprimés relativement au répertoire du
# projet pff $1
local pffdir="$1"
find "$pffdir/pff/Base" -type f | sed "s|^$pffdir/pff/Base/||" | grep -v '__pv-.*__$'
}
function pff_get_rfile() {
# obtenir le chemin relatif du fichier $1 exprimé par rapport au répertoire
# du projet pff $2. Si c'est un fichier d'un répertoire de profil,
# l'exprimer comme un chemin du répertoire de projet, e.g pff/Profile/path
# devient path
# retourner 1 si le chemin est invalide (est situé en dehors de pffdir ou
# pas dans un répertoire de profil)
local rfile="$1" pffdir="$2"
setx rfile=abspath "$rfile"
[ "${rfile#$pffdir/}" != "$rfile" ] || return 1
rfile="${rfile#$pffdir/}"
if [[ "$rfile" == pff/*/* ]]; then
rfile="${rfile#pff/*/}"
elif [[ "$rfile" == pff/* ]]; then
return 1
fi
echo "$rfile"
}
function pff_get_pfile() {
# obtenir le chemin du fichier $1 exprimé par rapport au répertoire du
# profil $2 dans le répertoire de projet $3
# retourner 1 si le chemin est invalide (est situé en dehors de pffdir ou
# pas dans un répertoire de profil)
local pfile="$1" profile="$2" pffdir="$3"
setx pfile=abspath "$pfile"
[ "${pfile#$pffdir/}" != "$pfile" ] || return 1
pfile="${pfile#$pffdir/}"
if [[ "$pfile" == pff/*/* ]]; then
pfile="${pfile#pff/*/}"
elif [[ "$pfile" == pff/* ]]; then
return 1
fi
echo "$pffdir/pff/$profile/$pfile"
}
function pff_get_bfile() { pff_get_pfile "$1" Base "$2"; }
function pff_get_Cfile() { pff_get_pfile "$1" Common "$2"; }
function pff_get_cfile() { pff_get_pfile "$1" Current "$2"; }
function pff_get_vlfiles_nostrip() {
# afficher tous les fichiers de version
local pffdir="$1" rfile="$2" profile="${3:-Base}" version="$4"
[ -d "$pffdir/pff/$profile" ] || return
if [ -n "$version" ]; then
if [ -n "$rfile" ]; then
find "$pffdir/pff/$profile" \
-type f -path "$pffdir/pff/$profile/${rfile}__pv-${version}__" -o \
-type l -path "$pffdir/pff/$profile/${rfile}__pv-${version}__"
else
find "$pffdir/pff/$profile" \
-type f -name "*__pv-${version}__" -o \
-type l -name "*__pv-${version}__"
fi
else
if [ -n "$rfile" ]; then
find "$pffdir/pff/$profile" \
-type f -path "$pffdir/pff/$profile/${rfile}__pv-*__" -o \
-type l -path "$pffdir/pff/$profile/${rfile}__pv-*__"
else
find "$pffdir/pff/$profile" \
-type f -name "*__pv-*__" -o \
-type l -name "*__pv-*__"
fi
fi
}
function pff_get_vlfiles() {
local pffdir="$1" rfile="$2" profile="${3:-Base}" version="$4"
pff_get_vlfiles_nostrip "$@" | sed "s|^$pffdir/pff/$profile/||"
}
function pff_is_nomerge() {
local file="$1" pffdir="$2"
local nomerge rfile
setx rfile=pff_get_rfile "$file" "$pffdir"
setx file=basename -- "$rfile" # utilisé pour le match sur le nom du fichier
for nomerge in "${NOMERGES[@]}"; do
if [[ "$nomerge" == */* ]]; then
# matcher sur le chemin relatif
if eval "[[ $(qval "$rfile") == $(qwc "$nomerge") ]]"; then
return 0
fi
else
# matcher uniquement sur le nom du fichier
if eval "[[ $(qval "$file") == $(qwc "$nomerge") ]]"; then
return 0
fi
fi
done
return 1
}
function pff_sync_vlfiles() {
# synchroniser les fichiers de version $3..@ dans tous les répertoires de
# profil, ou seulement le répertoire de profil $2 si la valeur n'est pas
# vide.
local pffdir="$1"; shift
local profile="$1"; shift
local -a profiles
if [ -n "$profile" ]; then
profiles=("$profile")
else
array_from_lines profiles "$(pff_get_user_profiles "$pffdir")"
fi
local vlfile rfile prefix pfile plink tmp
for vlfile in "$@"; do
rfile="${vlfile%__pv-*__}"
for profile in "${profiles[@]}"; do
prefix="$pffdir/pff/$profile"
flexists "$prefix/$rfile" || continue
pfile="$prefix/$vlfile"
setx plink=multiups "$profile/$vlfile" "Base/$vlfile"
if [ -L "$pfile" ]; then
# correction éventuelle du lien existant
setx tmp=readlink "$pfile"
[ "$tmp" == "$plink" ] || ln -sfT "$plink" "$pfile"
else
ln -sf "$plink" "$pfile" || return
fi
done
done
}
function pff_select_profile() {
# sélectionner le profil $1 dans le projet pff $2. créer d'abord le profil
# s'il n'existe pas.
local profile="$1" pffdir="$2"
# créer le répertoire de profil si nécessaire
mkdir -p "$pffdir/pff/$profile" || return 1
# mettre à jour les liens
local -a lfiles; local lfile src dest
setx -a lfiles=pff_get_local_files "$pffdir"
for lfile in "${lfiles[@]}"; do
src="$pffdir/pff/Current/$lfile"
if [ -f "$pffdir/pff/$profile/$lfile" ]; then
dest="$profile/$lfile"
elif [ "$profile" != Common -a -f "$pffdir/pff/Common/$lfile" ]; then
dest="Common/$lfile"
else
dest="Base/$lfile"
fi
setx dest=multiups "Current/$lfile" "$dest"
[ -L "$src" ] || mkdirof "$src"
ln -sfT "$dest" "$src"
done
# maj du lien "profil courant"
ln -sfT "$profile" "$pffdir/pff/.Current"
}
function pff_autoinit() {
# vérifications automatiques: créer les répertoires de base nécessaire au
# fonctionnement de pff dans le projet pff $1
local pffdir="$1" profile mkdir
[ -d "$pffdir/pff/Current" ] || mkdir -p "$pffdir/pff/Current"
[ -d "$pffdir/pff/Base" ] || mkdir -p "$pffdir/pff/Base"
# tous les fichiers du profil Base doivent être en lecture seule
find "$pffdir/pff/Base" -type f -perm /222 -exec chmod a-w '{}' +
# Créer les répertoires de MKDIRS
for mkdir in "${MKDIRS[@]}"; do
mkdir -p "$pffdir/$mkdir"
done
return 0
}
function pff_autoselect() {
# vérification automatiques: sélectionner le premier profil défini si aucun
# profil n'est sélectionné dans le projet pff $1
local pffdir="$1" profile
if [ ! -L "$pffdir/pff/.Current" ]; then
setx profile=pff_get_first_profile "$pffdir"
[ -n "$profile" ] || profile=Base
enote "Autosélection du profil $profile"
pff_select_profile "$profile" "$pffdir"
fi
}
function pff_autofix() {
pff_autoinit "$1"
pff_autoselect "$1"
}

94
pff
View File

@ -26,10 +26,10 @@ PFFCONFVARS=(
"DISTTYPE=auto//Type de distribution upstream: full ou patch"
-a
"ORIGEXTS=//Extensions origines"
"PROTECTS=//Fichiers locaux à protéger lors de l'intégration e.g /dir/, /file, etc."
"PROTECTS=//Fichiers locaux à protéger lors de l'intégration au format rsync e.g /dir/, /file, etc."
"MKDIRS//Répertoires qui doivent toujours exister"
"FILTERS//Filtres appliqués aux fichiers lors de l'intégration"
"NOMERGES=//Fichiers qu'il ne faut pas chercher à fusionner"
"FILTERS//Filtres appliqués aux fichiers lors de l'intégration, de la forme 'filespec:filter'. Cf la doc pour le détail du format"
"NOMERGES=//Fichiers qu'il ne faut pas chercher à fusionner. Cf la doc pour le détail du format"
)
if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then
@ -152,6 +152,44 @@ sont:
USAGE
$scriptname [options]
CONFIGURATION
Le fichier $PFFCONF contient des variables qui conditionnent le comportement de
pff:
PROTECTS -- liste de spécifications de fichiers ou de répertoires à protéger
lors de l'intégration. Ces spécifications sont au format rsync, e.g
/dir/, /file, etc.
FILTERS -- liste de définitions de filtres à appliquer aux fichiers lors de
l'intégration. ces spécifications sont de la forme 'filespec:filter'.
Les spécifications de fichier peuvent contenir des wildcards et sont de
deux sortes:
- sans chemin, e.g 'myfile' ou '*.c', tous les fichiers de ce nom
correspondent
- avec un chemin, e.g '/myfile', 'path/to/*.jsp', la correspondance est
cherchée relativement au répertoire du projet. ainsi '/*.c' ne matche
que les fichiers ayant l'extension .c situés dans le répertoire du
projet
Les filtres disponibles sont:
nl2lf -- forcer le caractère de fin de ligne à LF
nl2crlf -- forcer le caractère de fin de ligne à CR+LF
nl2cr -- forcer le caractère de fin de ligne à CR
normalize_properties -- normaliser fichier de propriétés java
Il est possible de créer de nouveaux filtres en définissant des
fonctions de la forme pff_filter_NAME(). Ces fonctions, si elles sont
appelées sans argument, doivent filtrer l'entrée standard. Si un
argument est spécifié, il faut filtrer ce fichier-là.
NOMERGES -- liste de spécifications de fichiers qu'il ne faut pas chercher à
fusionner. Les spécifications de fichier peuvent contenir des wildcards
et sont de deux sortes:
- sans chemin, e.g 'myfile' ou '*.c', tous les fichiers de ce nom
correspondent
- avec un chemin, e.g '/myfile', 'path/to/*.jsp', la correspondance est
cherchée relativement au répertoire du projet. ainsi '/*.c' ne matche
que les fichiers ayant l'extension .c situés dans le répertoire du
projet
COMMANDES / OPTIONS
Les arguments du script dépendent de la commande utilisée. Les commandes
supportées sont:
@ -456,6 +494,7 @@ function is_nomerge() {
for nomerge in "${NOMERGES[@]}"; do
if [[ "$nomerge" == */* ]]; then
# matcher sur le chemin relatif
nomerge="${nomerge#/}"
if eval "[[ $(qval "$rfile") == $(qwc "$nomerge") ]]"; then
return 0
fi
@ -572,6 +611,39 @@ function pff_filter_normalize_properties() {
return $r
fi
}
function pff_filter_nl2lf() {
if [ $# -eq 0 ]; then
_nl2lf
else
local mode r
mode="$(fix_mode "$1")"
doinplace "$1" _nl2lf; r=$?
unfix_mode "$1" "$mode"
return $r
fi
}
function pff_filter_nl2crlf() {
if [ $# -eq 0 ]; then
_nl2crlf
else
local mode r
mode="$(fix_mode "$1")"
doinplace "$1" _nl2crlf; r=$?
unfix_mode "$1" "$mode"
return $r
fi
}
function pff_filter_nl2cr() {
if [ $# -eq 0 ]; then
_nl2cr
else
local mode r
mode="$(fix_mode "$1")"
doinplace "$1" _nl2cr; r=$?
unfix_mode "$1" "$mode"
return $r
fi
}
function apply_filter() {
# Appliquer les filtres définis au fichier $1 dans le projet pff $2
@ -580,12 +652,22 @@ function apply_filter() {
# produite, 2 si aucun filtre n'existe pour ce fichier
local pfile="$1" pffdir="$2"
local realfile="${3:-$pfile}"
local rfile ffile filter r=2
local rfile ffile filter r=2 filedir filespec
setx rfile=get_rfile "$realfile" "$pffdir"
setx file=basename -- "$rfile" # utilisé pour le match sur le nom du fichier
for filter in "${FILTERS[@]}"; do
splitpair "$filter" ffile filter
if [ "$ffile" == "$rfile" ]; then
"pff_filter_$filter" "$pfile" && r=0 || r=1
if [[ "$ffile" == */* ]]; then
# matcher sur le chemin relatif
ffile="${ffile#/}"
if eval "[[ $(qval "$rfile") == $(qwc "$ffile") ]]"; then
"pff_filter_$filter" "$pfile" && r=0 || r=1
fi
else
# matcher uniquement sur le nom du fichier
if eval "[[ $(qval "$file") == $(qwc "$ffile") ]]"; then
"pff_filter_$filter" "$pfile" && r=0 || r=1
fi
fi
done
return $r

332
repoctl Executable file
View File

@ -0,0 +1,332 @@
#!/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
get URL [VARs...]
Afficher les propriétés du dépôt spécifié. VARs est une liste de
variables à afficher pour le dépôt, séparés par le caractère tabulation.
edit URL var=value...
Modifier les propriétés du dépôt. Consulter l'API pour la liste exacte
des propriétés pouvant être modifiées. Avec gitea 1.9.3, il y a au moins
celles-là:
name
description
website
private
default_branch
delete URL
Supprimer le dépôt spécifié"
}
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 repourl desc payload result
local -a vars
if [ -n "$user" -a "$user" != "$gogs_user" ]; then
# créer un dépôt dans une organisation
url="$gogs_url/api/v1/org/$user/repos"
repourl="$gogs_url/$user/$path"
else
# créer un dépôt pour un utilisateur
url="$gogs_url/api/v1/user/repos"
repourl="$gogs_url/$gogs_user/$path"
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"
isatty && estep "Création du dépôt $repourl"
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[@]}"
}
################################################################################
function get_action() {
case "$rtype" in
#gitolite) ;;
gogs|gitea)
gogs_setvars
gogs_get_action "$@"
;;
*) die "$rtype: type de dépôt non supporté";;
esac
}
function gogs_get_action() {
local url repourl payload result
local -a vars
url="$gogs_url/api/v1/repos/$user/$path"
repourl="$gogs_url/$user/$path"
[ $# -gt 0 ] && vars=("$@") || vars=("")
local HTTP_METHOD=GET
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 déplacement du dépôt
url: $url
payload: $payload
result: $result"
isatty && estep "Attributs du dépôt $repourl"
echo "$result" | json_get "${vars[@]}"
}
################################################################################
function edit_action() {
case "$rtype" in
#gitolite) ;;
gogs|gitea)
gogs_setvars
gogs_edit_action "$@"
;;
*) die "$rtype: type de dépôt non supporté";;
esac
}
function gogs_edit_action() {
local url repourl payload result
local -a vars
url="$gogs_url/api/v1/repos/$user/$path"
repourl="$gogs_url/$user/$path"
vars=()
while [[ "$1" == *=* ]]; do
vars+=("$1")
shift
done
setx payload=json_build "${vars[@]}"
[ $# -gt 0 ] && vars=("$@") || vars=("")
local HTTP_METHOD=PATCH
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"
isatty && estep "Mise à jour du dépôt $repourl"
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 repourl payload result
url="$gogs_url/api/v1/repos/$user/$path"
repourl="$gogs_url/$user/$path"
local HTTP_METHOD=DELETE
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 suppression du dépôt
url: $url
payload: $payload
result: $result"
isatty && estep "Suppression du dépôt $repourl"
[ -n "$result" ] && echo "$result"
return 0
}
################################################################################
action=
args=(
--help '$exit_with display_help'
-c,--create action=create
-l,--list action=list
-g,--get action=get
-e,--edit action=edit
-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 "$@";;
g|get|s|show) get_action "$@";;
e|edit) edit_action "$@";;
d|del|delete|rm|remove) delete_action "$@";;
esac

4
sqlcsv
View File

@ -1159,7 +1159,7 @@ public class sqlcsv {
int i = 0, max = args.length;
while (i < max) {
String arg = args[i];
if (arg.substring(0, 2).equals("-J") || arg.substring(0, 2).equals("+J")) {
if (arg.length() >= 2 && (arg.substring(0, 2).equals("-J") || arg.substring(0, 2).equals("+J"))) {
die("L'option -J doit être spécifiée en premier", null);
} else if (arg.equals("-C") || arg.equals("--config")) {
config = getArg(args, ++i, "Vous devez spécifier le fichier de configuration");
@ -1316,7 +1316,7 @@ public class sqlcsv {
if (resetPrefs) throw new Exit();
else throw new Exit("Vous devez spécifier l'url de connexion");
}
if (usePrefs) {
if (usePrefs && connid != null) {
log.fine("Enregistrement de la valeur connid=" + connid);
prefs.put("lastConnid", connid);
}

View File

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

View File

@ -202,7 +202,7 @@ Les lignes commençant par # sont des commentaires et sont ignorées
0 1 * * *
osvar FIRST=default SECOND
echo \"first is $FIRST and second is $SECOND\"
echo \"first is \$FIRST and second is \$SECOND\"
En temps normal, FIRST vaut la valeur par défaut 'default' et SECOND vaut la
chaine vide ''. Si on appelle '$scriptname -v FIRST=1 -v SECOND=2' alors ces

90
woclean-logs Executable file
View File

@ -0,0 +1,90 @@
#!/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: supprimer les fichiers de log inutiles dans /var/log/WebObjects
USAGE
$scriptname [options]
OPTIONS
-u, --useless
Supprimer les logs inutiles. C'est l'option par défaut
-a, --all
Supprimer tous les logs
-t, --today
Supprimer tous les logs du jour"
}
what=useless
args=(
--help '$exit_with display_help'
-u,--useless what=useless
-a,--all what=all
-t,--today what=today
)
parse_args "$@"; set -- "${args[@]}"
run_as_root "$@"
count=0
cd /var/log/WebObjects || die
case "$what" in
useless)
einfo "Suppression des fichiers de log inutiles dans /var/log/WebObjects"
ask_yesno "Voulez-vous continuer?" O || exit
/bin/ls | while read f; do
[ "${f%-[0-9]}" != "$f" ] && continue
# Tester la presence de "Waiting for requests..."
if ! grep -q 'Waiting for requests...$' "$f"; then
echo "$f: no 'Waiting for Requests...'"
/bin/rm -f "$f" || die
count=$(($count + 1))
continue
fi
# Tester la presence de contenu apres Waiting for requests..."
if grep -v "CookieParser: Found a null cookie value in: " "$f" | tail -n 1 | grep -q 'Waiting for requests...$'; then
echo "$f: empty log"
/bin/rm -f "$f" || die
count=$(($count + 1))
continue
fi
done
;;
all)
einfo "Suppression de TOUS les fichiers de logs dans /var/log/WebObjects"
ask_yesno "Voulez-vous continuer?" O || exit
/bin/ls | while read f; do
if [ "${f%-[0-9]}" = "$f" ]; then
echo "$f"
/bin/rm -f "$f" || exit 1
count=$(($count + 1))
fi
done
;;
today)
einfo "Suppression des fichiers de logs DU JOUR dans /var/log/WebObjects"
ask_yesno "Voulez-vous continuer?" O || exit
now="$(date +%Y%m%d)"
/bin/ls | grep -- "-[0-9]*\\.$now[0-9]*$" | while read f; do
echo "$f"
/bin/rm -f "$f" || exit 1
count=$(($count + 1))
done
;;
esac
if [ $count -gt 0 ]; then
enote "$count fichiers supprimés"
fi