#!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 function display_help() { uecho "$scriptname: Outils pour gérer une installation de DokuWiki USAGE $scriptname cmd [options] COMMANDES newpage titre Créer une nouvelle page avec le titre spécifié newlog [titre] Créer une nouvelle page datée du jour. Equivalent à newpage --log. find filtre Chercher les pages dont le nom correspondent au filtre edit filtre Editer la première page qui correspond au filtre commit [msg] Enregistrer les modifications dans le gestionnaire de version. sync Synchroniser un dokuwiki local vers une installation système. Requière les droits de root. generate srcdir Générer la documentation du projet srcdir dans un espace de nom" } SCRIPT_ALIASES=( dwa:newpage dwl:find dwe:edit dwci:commit dwsync:sync ) if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then # créer les liens scriptname="$(basename "$0")" for alias in "${SCRIPT_ALIASES[@]}"; do alias="${alias%:*}" ln -s "$scriptname" "$alias" done exit 0 fi source "$(dirname "$0")/ulib/ulib" && urequire DEFAULTS || exit 1 # Traduire le nom du script for script_alias in "${SCRIPT_ALIASES[@]}"; do splitpair "$script_alias" src dest if [ "$scriptname" == "$src" ]; then eval "set -- $dest \"\$@\"" scriptname=dokuwiki break fi done DWCOMMIT=1 set_defaults dokuwiki function __check_dwdir0() { [ -f "$1/doku.php" -a -d "$1/data/pages" -a -d "$1/data/media" ] } function __check_dwdir1() { [ -f "$1/.dokuwiki" ] } function __check_dwdir() { __check_dwdir0 "$1" && return 0 __check_dwdir1 "$1" && return 0 return 1 } function find_dwdir() { # trouver le répertoire du dokuwiki correspondant au répertoire $1 et # retourner 0. Retourner 1 si $1 n'est pas dans un répertoire de dokuwiki. local dwdir="$(abspath "${1:-.}")" while [ "$dwdir" != "/" ]; do if __check_dwdir "$dwdir"; then echo "$dwdir" return 0 fi dwdir="$(dirname "$dwdir")" done if [ -n "$DOKUWIKIDIR" ] && __check_dwdir "$DOKUWIKIDIR"; then echo "$(abspath "$DOKUWIKIDIR")" return 0 fi return 1 } function get_pagesdir() { # Obtenir le répertoire des pages du dokuwiki $1, qui a déjà été normalisé # avec find_dwdir() if [ -f "$1/doku.php" ]; then echo "$1/data/pages" elif [ -f "$1/.dokuwiki" ]; then echo "$1" fi } function get_mediadir() { # Obtenir le répertoire de media du dokuwiki $1, qui a déjà été normalisé # avec find_dwdir() if [ -f "$1/doku.php" ]; then echo "$1/data/media" elif [ -f "$1/.dokuwiki" ]; then echo "$1/_media" fi } function in_datadir() { # retourner 0 si le répertoire ou le fichier $1 est dans le répertoire pages # ou media d'un dokuwiki. local data dwdir data="$(abspath "${1:-.}")" dwdir="$(find_dwdir "$data")" || return 1 local pagesdir="$(get_pagesdir "$dwdir")" [ "$data" == "pagesdir" -o "${data#$pagesdir/}" != "$data" ] && return 0 local mediadir="$(get_mediadir "$dwdir")" [ "$data" == "mediadir" -o "${data#$mediadir/}" != "$data" ] && return 0 return 1 } function compute_ns() { # calculer le namespace correspondant au fichier ou au répertoire $1 et # retourner 0. Le namespace est retourné normalisé, c'est à dire "" si pas # de namespace, et "ns:" pour le namespace ns. # retourner 1 si le namespace n'a pas pu être calculé, notamment parce que # $1 n'est pas un fichier du dokuwiki. local datadir dwdir ns datadir="$(abspath "${1:-.}")" if [ -e "$datadir" ]; then [ -d "$datadir" ] || datadir="$(dirname "$datadir")" fi in_datadir "$datadir" || return 1 dwdir="$(find_dwdir "$datadir")" || return 1 local mediadir="$(get_mediadir "$dwdir")" if [ "$datadir" == "mediadir" ]; then return 0 elif [ "${datadir#$mediadir/}" != "$datadir" ]; then ns="${datadir#$mediadir/}" echo "${ns//\//:}" return 0 fi local pagesdir="$(get_pagesdir "$dwdir")" if [ "$datadir" == "pagesdir" ]; then return 0 elif [ "${datadir#$pagesdir/}" != "$datadir" ]; then ns="${datadir#$pagesdir/}" echo "${ns//\//:}" return 0 fi return 1 } function norm_ns() { # normaliser un namespace: le faire terminer par ":" s'il est non vide. local ns="$1" if [ -n "$ns" ]; then [ "${ns%:}" == "$ns" ] && ns="$ns:" echo "$ns" fi } function clean_ns() { # supprimer le ":" de fin d'un namespace [ -n "$1" ] && echo "${1%:}" } function __create() { local dwdir="$1" file="$2" title="$3" __newfiles="$4" estepi "Création de la page $(ppath "$file")" echo "# -*- coding: utf-8 mode: text -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ===== $title ===== " >"$file" [ -n "$__newfiles" ] && array_add "$__newfiles" "$file" [ -n "$edit" ] && "${EDITOR:-vi}" +5 "$file" return 0 } function __addtostart() { local dwdir="$1" ns="$2" name="$3" title="$4" __newfiles="$5" __modfiles="$6" local basestart="$(get_pagesdir "$dwdir")/${ns//://}start" local start="$basestart.txt" mkdirof "$start" if [ -f "$start" ]; then [ -n "$__modfiles" ] && array_add "$__modfiles" "$start" else echo >"$start" "\ # -*- coding: utf-8 mode: text -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 " [ -n "$__newfiles" ] && array_add "$__newfiles" "$start" fi quietgrep "=== Pages non classées ===" "$start" || echo >>"$start" "\ ===== Pages non classées ===== " echo " * [[$ns$name|$title]]" >>"$start" } function __strip_dwdir() { if [ "$1" == "$dwdir" ]; then echo . else echo "${1#$dwdir/}" fi } function __commit() { local dwdir="$1" msg="$2" [ -d "$dwdir/.git" ] || return 0 local -a __newfiles __modfiles [ -n "$3" ] && array_copy __newfiles "$3" array_map __newfiles __strip_dwdir [ -n "$4" ] && array_copy __modfiles "$4" array_map __modfiles __strip_dwdir cwd="$(pwd)" cd "$dwdir" if [ -n "${__newfiles[*]}" -o -n "${__modfiles[*]}" ]; then "$scriptdir/uproject" add "${__newfiles[@]}" "${__modfiles[@]}" else "$scriptdir/uproject" add . fi "$scriptdir/uproject" commit "$msg" "${__newfiles[@]}" "${__modfiles[@]}" cd "$cwd" } ################################################################################ function newpage_help() { uecho "$scriptname newpage: créer une nouvelle page de wiki USAGE $scriptname newpage PAGE PAGE est de la forme [ns:]titre - ns est l'espace de nom dans lequel la nouvelle page doit être créée. - titre est le titre de la nouvelle page. - nom est le nom du fichier sur disque. il est calculé à partir de titre. Toutes ces valeurs peuvent être forcées individuellement. OPTIONS -d DWDIR Spécifier le répertoire du dokuwiki -t TITRE Forcer la valeur du titre de la page au lieu de la calculer à partir de PAGE. -s NS Spécifier l'espace de nom dans lequel créer la nouvelle page au lieu de le calculer à partir de PAGE ou du répertoire courant. -n NOM Forcer la valeur du nom de fichier à utiliser au lieu de la calculer à partir de PAGE. --log Dater la nouvelle page de la date du jour. Cette option est utile pour documenter des opérations journalières. -c Ne pas lancer l'édition du fichier après l'avoir créé. Si DWCOMMIT=1, ne pas lancer l'enregistrement des modifications dans le gestionnaire de version. -o Ne pas rajouter la mention de la nouvelle page dans [[start]]" } function newpage_cmd() { eval "$(utools_local)" local dwdir title ns name log local edit=1 addtostart=1 parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with newpage_help' \ -d:,--dwdir: dwdir= \ -t:,--title: title= \ -s:,--ns:,--namespace: ns= \ -n:,--name: name= \ -l,--log log=1 \ -c,--noedit edit= \ -o,--orphan addtostart= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" dwdir="$(find_dwdir "$dwdir")" || die "Impossible de trouver dokuwiki. Etes-vous dans le bon répertoire?" if [ -z "$ns" ]; then ns="$(compute_ns .)" fi if [ -z "$title" ]; then title="$1" if [ -n "$title" ]; then # éventuellement prendre le namespace dans le titre fourni en ligne # de commande if [ -z "$ns" ]; then ns="$(echo "$title" | awk '{ ns = tolower($0) if (match(ns, /^([-a-z0-9]+:)+/)) { print substr(ns, 1, RLENGTH - 1) } }')" [ -n "$ns" ] && title="${title:$((${#ns} + 1))}" fi elif [ -z "$log" ]; then read_value "Veuillez entrer un titre pour la page de wiki à créer" title fi fi ns="$(norm_ns "$ns")" if [ -z "$name" ]; then name="$(echo "$title" | awk '{ name = tolower($0) gsub(/[^- /a-z0-9]/, "", name) gsub(/\//, "-", name) gsub(/ +/, "-", name) print name }')" fi if [ -n "$log" ]; then title="$(date +"%d/%m/%Y")${title:+: $title}" name="$(date +"%Y-%m-%d")${name:+-$name}" fi read_value "Veuillez confirmer le nom de la page" name "$name" local basename="$name" local basefile="$(get_pagesdir "$dwdir")/${ns//://}$name" local file="$basefile.txt" if [ -f "$file" ]; then estepw "Le fichier $(ppath "$file") existe déjà." ask_yesno "Si vous continuez, un NOUVEAU fichier avec un suffixe numérique sera créé. Sinon, vous pouvez utiliser '$scriptname edit' pour modifier le fichier existant. Voulez-vous continuer?" O || return 1 fi local i=0 while [ -f "$file" ]; do i=$(($i + 1)) name="$basename-$i" file="$basefile-$i.txt" done mkdirof "$file" local -a newfiles modfiles __create "$dwdir" "$file" "$title" newfiles || return if [ -n "$addtostart" ]; then __addtostart "$dwdir" "$ns" "$name" "$title" newfiles modfiles || return fi if [ -n "$edit" -a -n "$DWCOMMIT" ]; then __commit "$dwdir" "newpage $title --> $ns$name" newfiles modfiles || return else estepi "dwci $(quoted_args "dwci newpage $title --> $ns$name")" fi return 0 } ################################################################################ function find_help() { uecho "$scriptname find: trouver une page USAGE $scriptname find OPTIONS -d DWDIR Spécifier le répertoire de dokuwiki -s NAMESPACE Restreindre la recherche à l'espace de nom spécifié" } function find_cmd() { eval "$(utools_local)" local dwdir ns parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with find_help' \ -d:,--dwdir: dwdir= \ -s:,--ns:,--namespace: ns= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" dwdir="$(find_dwdir "$dwdir")" || die "Impossible de trouver dokuwiki. Etes-vous dans le bon répertoire?" ns="$(clean_ns "$ns")" local filter="$1" local pages="$(get_pagesdir "$dwdir")" local searchdir="$pages" [ -n "$ns" ] && searchdir="$searchdir/${ns//://}" [ -d "$searchdir" ] || return 1 find "$searchdir" -type f -name "*.txt" | sed "s#^$pages/##g; s#.txt\$##g" | csort | { if [ -n "$filter" ]; then grep "$filter" else cat fi } } ################################################################################ function edit_help() { uecho "$scriptname edit: modifier une page USAGE $scriptname edit OPTIONS -d DWDIR Spécifier le répertoire de dokuwiki -s NAMESPACE Restreindre la recherche à l'espace de nom spécifié" } function edit_cmd() { eval "$(utools_local)" local dwdir ns parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with edit_help' \ -d:,--dwdir: dwdir= \ -s:,--ns:,--namespace: ns= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" dwdir="$(find_dwdir "$dwdir")" || die "Impossible de trouver dokuwiki. Etes-vous dans le bon répertoire?" ns="$(clean_ns "$ns")" local pagesdir="$(get_pagesdir "$dwdir")" local filter="$1" found= if [ -f "$filter" ]; then local file="$(abspath "$filter")" if [ "${file#$pagesdir/}" != "$file" -a "${file%.txt}" != "$file" ]; then page="${file#$pagesdir/}" page="${page%.txt}" found=1 fi fi if [ -z "$found" ]; then local -a pages array_from_lines pages "$(find_cmd -qq -d "$dwdir" -n "$ns" "$filter")" if [ "${#pages[*]}" -eq 0 ]; then eerror "Aucune page de ce nom n'a été trouvée" return 1 elif [ "${#pages[*]}" -eq 1 ]; then page="${pages[0]}" else simple_menu page pages -t "Pages trouvées" \ -m "Veuillez choisir la page à éditer" -d "${pages[0]}" fi fi local -a newfiles modfiles "${EDITOR:-vi}" "$pagesdir/$page.txt" array_add modfiles "$pagesdir/$page.txt" if [ -n "$DWCOMMIT" ]; then __commit "$dwdir" "edit ${page//\//:}" newfiles modfiles || return else estepi "dwci $(quoted_args "edit ${page//\//:}")" fi return 0 } ################################################################################ function commit_help() { uecho "$scriptname commit: enregistrer les modifications dans le gestionnaire de version USAGE $scriptname commit OPTIONS -d DWDIR Spécifier le répertoire de dokuwiki" } function commit_cmd() { eval "$(utools_local)" local dwdir parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with commit_help' \ -d:,--dwdir: dwdir= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" dwdir="$(find_dwdir "$dwdir")" || die "Impossible de trouver dokuwiki. Etes-vous dans le bon répertoire?" __commit "$dwdir" "$*" || return return 0 } ################################################################################ function sync_help() { uecho "$scriptname sync: synchroniser les fichiers vers un dokuwiki système. USAGE $scriptname sync [destdir] OPTIONS -d DWDIR Spécifier le répertoire du dokuwiki local --destdir DESTDIR Spécifier le répertoire du dokuwiki système. DESTDIR peut être un répertoire distant puisque la copie se fait avec rsync. Mais les paramètres --dirmode, --filemode et --owner sont alors ignorés. De plus, les indexes ne sont pas reconstruits. Il est aussi possible de spécifier DESTDIR comme argument de ce script. --dirmode DIRMODE --filemode FILEMODE --owner OWNER Spécifier les modes et propriétaires des fichiers dans le dokuwiki destination. --no-reindex Ne pas reconstruire l'index ni supprimer le cache après la mise à jour des fichiers." } function sync_cmd() { eval "$(utools_local)" local dwdir destdir noconf local dirmode filemode owner noreindex parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with sync_help' \ --noconf noconf=1 \ -d:,--dwdir: dwdir= \ --destdir: destdir= \ --dirmode: dirmode= \ --filemode: filemode= \ --owner: owner= \ -n,--no-reindex noreindex=1 \ --reindex noreindex= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$noconf" ]; then dwdir="$(find_dwdir "$dwdir")" || die "Impossible de trouver dokuwiki. Etes-vous dans le bon répertoire?" [ -f "$dwdir/.dokuwiki" ] && source "$dwdir/.dokuwiki" [ -z "$destdir" -a -n "$1" ] && destdir="$1" [ -n "$destdir" ] || destdir="$DWSYNC_DESTDIR" [ -n "$destdir" ] || die "Vous devez spécifier le répertoire de destination" [ -n "$dirmode" ] || dirmode="$DWSYNC_DIRMODE" [ -n "$filemode" ] || filemode="$DWSYNC_FILEMODE" [ -n "$owner" ] || owner="$DWSYNC_OWNER" [ -n "$url" ] || url="$DWSYNC_URL" fi run_as_root sync $(get_verbosity_option) --noconf -d "$dwdir" --destdir "$destdir" \ ${dirmode:+--dirmode "$dirmode"} \ ${filemode:+--filemode "$filemode"} \ ${owner:+--owner "$owner"} \ ${noreindex:+--no-reindex} "$@" local -a rsync reindexer rsync=(rsync -rltD --delete-after) reindexer=("$destdir/bin/indexer.php") if check_verbosity -v; then array_add rsync -v elif ! check_verbosity -c; then array_add rsync -q array_add reindexer -q fi local srcmdir="$(get_mediadir "$dwdir")" local srcpdir="$(get_pagesdir "$dwdir")" local destmdir="$destdir/data/media" local destpdir="$destdir/data/pages" etitle "Synchronisation des fichiers" if __check_dwdir0 "$dwdir"; then # pagesdir et mediadir séparés estep "$(ppath "$srcmdir") --> $(ppath "$destmdir")" "${rsync[@]}" "$srcmdir/" "$destmdir" estep "$(ppath "$srcpdir") --> $(ppath "$destpdir")" "${rsync[@]}" "$srcpdir/" "$destpdir" elif __check_dwdir1 "$dwdir"; then # mediadir dans pagesdir estep "$(ppath "$srcmdir") --> $(ppath "$destmdir")" "${rsync[@]}" "$srcmdir/" "$destmdir" estep "$(ppath "$srcpdir") --> $(ppath "$destpdir")" "${rsync[@]}" \ --exclude /.git --exclude /.dokuwiki --exclude /.udir \ --exclude /_media \ --exclude .svn \ "$srcpdir/" "$destpdir" fi eend if [ -n "$dirmode" ]; then etitle "dirmode=$dirmode" estep "$(ppath "$destmdir")" find "$destmdir" -type d -exec chmod "$dirmode" {} \; estep "$(ppath "$destpdir")" find "$destpdir" -type d -exec chmod "$dirmode" {} \; eend fi if [ -n "$filemode" ]; then etitle "filemode=$filemode" estep "$(ppath "$destmdir")" find "$destmdir" -type f -exec chmod "$filemode" {} \; estep "$(ppath "$destpdir")" find "$destpdir" -type f -exec chmod "$filemode" {} \; eend fi if [ -n "$owner" ]; then etitle "owner=$owner" estep "$(ppath "$destmdir")" chown -R "$owner" "$destmdir" estep "$(ppath "$destpdir")" chown -R "$owner" "$destpdir" eend fi if [ -z "$noreindex" -a -x "${reindexer[0]}" ]; then etitle "Réindexation des fichiers" "${reindexer[@]}" #estep "Suppression du cache" #local -a cachedirs #array_lsdirs cachedirs "$destdir/data/cache" #rm -rf "${cachedirs[@]}" estep "Invalidation du cache" touch "$destdir/conf/local.php" if [ -n "$owner" ]; then estep "owner=$owner" chown -R "$owner" "$destdir/data/index" fi eend fi } ################################################################################ function generate_help() { uecho "$scriptname generate: Générer la documentation d'un projet dans un espace de nom USAGE $scriptname generate [options] srcdir Si srcdir contient un fichier .dokuwikigen, ce fichier est sourcé pour générer la documentation. Les fonction setpage() et addpage() sont disponible. OPTIONS -d DWDIR Spécifier le répertoire du dokuwiki -s NS Spécifier l'espace de nom dans lequel créer la documentation. Par défaut, il s'agit de da:srcname où srcname est le nom de base de srcdir." } function generate_cmd() { eval "$(utools_local)" local dwdir ns title parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with generate_help' \ -d:,--dwdir: dwdir= \ -s:,--ns:,--namespace: ns= \ -t:,--title: title= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" dwdir="$(find_dwdir "$dwdir")" || die "Impossible de trouver dokuwiki. Etes-vous dans le bon répertoire?" local srcdir="$(abspath "${1:-.}")" [ -d "$srcdir" ] || die "Vous devez spécifier un répertoire de projet dont il faut générer la documentation" local srcname=$(basename "$srcdir") [ -n "$ns" ] || ns="da:$srcname" ns="$(norm_ns "$ns")" [ -n "$title" ] || title="$srcname" function setpage() { # Créer la page $1 avec le contenu de l'entrée standard # $2 est un namespace local en dessous de $ns local append if [ "$1" == "--append" ]; then append=1 shift fi local name="$1" localns="$2" name="$(awk '{ gsub(/_/, "") print tolower($0) }' <<<"$name")" # XXX normaliser le nom: en plus de le mettre en minuscule, il faut # supprimer certains caractères spéciaux comme '_'. en faire la liste? ns="$(norm_ns "$ns")" [ -n "$localns" ] && local ns="$(norm_ns "$ns$localns")" local basefile="$(get_pagesdir "$dwdir")/${ns//://}$name" local file="$basefile.txt" mkdirof "$file" if [ -f "$file" ]; then local -a __newfiles array_from_lines __newfiles "$(<"$newfiles")" array_contains __newfiles "$file" || echo "$file" >>"$modfiles" else echo "$file" >>"$newfiles" fi if [ -n "$append" ]; then cat >>"$file" else estepi "$(ppath "$file")" cat >"$file" fi } function addpage() { # ajouter le contenu de l'entrée standard à la page $1 setpage --append "$@" } function setmedia() { # Créer le fichier de media $2 en copiant le contenu du fichier $1 # $3 est un namespace local en dessous de $ns local source="$1" name="$2" localns="$3" name="$(awk '{ gsub(/_/, "") print tolower($0) }' <<<"$name")" # XXX normaliser le nom: en plus de le mettre en minuscule, il faut # supprimer certains caractères spéciaux comme '_'. en faire la liste? ns="$(norm_ns "$ns")" [ -n "$localns" ] && local ns="$(norm_ns "$ns$localns")" local file="$(get_mediadir "$dwdir")/${ns//://}$name" mkdirof "$file" if [ -f "$file" ]; then local -a __newfiles array_from_lines __newfiles "$(<"$newfiles")" array_contains __newfiles "$file" || echo "$file" >>"$modfiles" else echo "$file" >>"$newfiles" fi estepi "$(ppath "$file")" cat "$source" >"$file" } function gendefault() { setpage start <<<"===== $title ===== " if [ -f README.txt ]; then { awk 'NR==1 && $0 ~ /^#.*-\*-.*coding:/ {next} {print}' " "$cmd" --help echo "" } | setpage "$cmdname" if [ -n "$first" ]; then addpage start <<<"==== Outils ====" first= fi addpage start <<<" * [[$ns$cmdname]]" done eend } local newfiles modfiles ac_set_tmpfile newfiles ac_set_tmpfile modfiles ( cd "$srcdir" if [ -x .dokuwikigen ]; then ./.dokuwikigen elif [ -f .dokuwikigen ]; then source ./.dokuwikigen else gendefault fi array_from_lines newfiles "$(<"$newfiles")" array_from_lines modfiles "$(<"$modfiles")" if [ -n "$DWCOMMIT" ]; then __commit "$dwdir" "generate $srcdir" newfiles modfiles else estepi "dwci $(quoted_args "generate $srcdir")" fi ) } ################################################################################ parse_opts + "${PRETTYOPTS[@]}" \ --help '$exit_with display_help' \ @ args -- "$@" && set -- "${args[@]}" || die "$args" cmd="$1"; shift case "$cmd" in "") exit_with display_help;; newpage|createpage|addpage|page|p|new|n|create|c|add|a) newpage_cmd "$@";; newlog|createlog|log|blog|date|d) newpage_cmd --log "$@";; find|f|search|s|list|l) find_cmd "$@";; edit|e|vim|vi) edit_cmd "$@";; commit|ci) commit_cmd "$@";; sync) sync_cmd "$@";; generate|gen|g) generate_cmd "$@";; *) die "$cmd: commande incorrecte";; esac