957 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			957 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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 awk
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: Outils pour gérer une installation de MediaWiki
 | |
| 
 | |
| 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 le mediawiki vers la base de données.
 | |
|     generate srcdir
 | |
|         Générer la documentation du projet srcdir dans un espace de nom"
 | |
| }
 | |
| 
 | |
| SCRIPT_ALIASES=(
 | |
|     mwa:newpage
 | |
|     mwl:find
 | |
|     mwe:edit
 | |
|     mwci:commit
 | |
|     mwsync: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
 | |
| 
 | |
| # 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=mediawiki
 | |
|         break
 | |
|     fi
 | |
| done
 | |
| 
 | |
| REVSHA1="r.rev_sha1"
 | |
| if [ -n "$FIXREVSHA1" ]; then
 | |
|     # Si l'instance de mediawiki attaquée est trop vielle, il n'y a pas le champ
 | |
|     # revision.rev_sha1 et une erreur se produit lors de l'accès à la base de
 | |
|     # données. Faire FIXREVSHA1=1 pour pouvoir au moins faire l'export des
 | |
|     # données avec init.
 | |
|     REVSHA1="'' AS rev_sha1"
 | |
| fi
 | |
| 
 | |
| MWCOMMIT=1
 | |
| set_defaults mediawiki
 | |
| 
 | |
| function check_mwdir() {
 | |
|     [ -f "$1/.mediawiki" ]
 | |
| }
 | |
| function find_mwdir() {
 | |
|     # trouver le répertoire du mediawiki correspondant au répertoire $1 et
 | |
|     # retourner 0. Retourner 1 si $1 n'est pas dans un répertoire de mediawiki.
 | |
|     local mwdir="$(abspath "${1:-.}")"
 | |
|     while [ "$mwdir" != "/" ]; do
 | |
|         if check_mwdir "$mwdir"; then
 | |
|             echo "$mwdir"
 | |
|             return 0
 | |
|         fi
 | |
|         mwdir="$(dirname "$mwdir")"
 | |
|     done
 | |
|     if [ -n "$MEDIAWIKIDIR" ] && check_mwdir "$MEDIAWIKIDIR"; then
 | |
|         echo "$(abspath "$MEDIAWIKIDIR")"
 | |
|         return 0
 | |
|     fi
 | |
|     return 1
 | |
| }
 | |
| function in_mwdir() {
 | |
|     # retourner 0 si le répertoire ou le fichier $1 est dans le répertoire d'un
 | |
|     # mediawiki.
 | |
|     local data mwdir
 | |
|     data="$(abspath "${1:-.}")"
 | |
|     mwdir="$(find_mwdir "$data")" || return 1
 | |
|     [ "$data" == "mwdir" -o "${data#$mwdir/}" != "$data" ] && return 0
 | |
|     return 1
 | |
| }
 | |
| 
 | |
| function mw_local() {
 | |
|     echo "local MWDBHOST MWDBPORT MWDBUSER MWDBPASS MWDBNAME MWPREFIX MWSITEURL"
 | |
| }
 | |
| function load_mwconf() {
 | |
|     local mwdir="$1"
 | |
|     [ -f "$mwdir/.mediawiki" ] || die "Impossible de trouver le fichier de configuration"
 | |
|     source "$mwdir/.mediawiki"
 | |
| }
 | |
| function mwmysql() {
 | |
|     "$scriptdir/mysqlcsv" -h "$MWDBHOST" ${MWDBPORT:+-P "$MWDBPORT"} -u "$MWDBUSER" ${MWDBPASS:+-p"$MWDBPASS"} -n "$MWDBNAME" "$@"
 | |
| }
 | |
| function mwexportpages() {
 | |
|     mwmysql "\
 | |
| SELECT p.page_id, p.page_title,
 | |
| r.rev_user, r.rev_user_text, r.rev_text_id AS rev_id, $REVSHA1,
 | |
| t.old_id AS text_id, t.old_flags AS text_flags, t.old_text AS text_content
 | |
| FROM ${MWPREFIX}page p
 | |
| INNER JOIN ${MWPREFIX}revision r ON p.page_latest = r.rev_id
 | |
| INNER JOIN ${MWPREFIX}text t ON r.rev_text_id = t.old_id
 | |
| WHERE p.page_namespace = 0;"
 | |
| }
 | |
| function mwexportfiles() {
 | |
|     mwmysql "\
 | |
| SELECT p.page_id, p.page_title,
 | |
| r.rev_user, r.rev_user_text, r.rev_text_id AS rev_id, $REVSHA1,
 | |
| t.old_id AS text_id, t.old_flags AS text_flags, t.old_text AS text_content
 | |
| FROM ${MWPREFIX}page p
 | |
| INNER JOIN ${MWPREFIX}revision r ON p.page_latest = r.rev_id
 | |
| INNER JOIN ${MWPREFIX}text t ON r.rev_text_id = t.old_id
 | |
| WHERE p.page_namespace = 6;"
 | |
| }
 | |
| 
 | |
| function __ensure_mwdir() {
 | |
|     mwdir="$(find_mwdir "$mwdir")" || die "Impossible de trouver mediawiki. Etes-vous dans le bon répertoire?"
 | |
|     load_mwconf "$mwdir"
 | |
| }
 | |
| 
 | |
| function __check_exists() {
 | |
|     # vérifier si le fichier nommé $1 existe dans $mwdir
 | |
|     [ -n "$(find "$mwdir" -name "$(basename "$1")")" ]
 | |
| }
 | |
| 
 | |
| function __create() {
 | |
|     local mwdir="$1" file="$2" name="$3" title="$4" __newfiles="$5" __modfiles="$6"
 | |
| 
 | |
|     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"
 | |
|     echo "\"${name//\"/\\\"}\",,," >>"$mwdir/.mwpages"
 | |
|     [ -n "$__newfiles" ] && array_add "$__newfiles" "$file"
 | |
|     [ -n "$__modfiles" ] && array_add "$__modfiles" "$mwdir/.mwpages"
 | |
|     [ -n "$edit" ] && "${EDITOR:-vi}" +5 "$file"
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function __strip_mwdir() {
 | |
|     if [ "$1" == "$mwdir" ]; then
 | |
|         echo .
 | |
|     else
 | |
|         echo "${1#$mwdir/}"
 | |
|     fi
 | |
| }
 | |
| function __commit() {
 | |
|     local mwdir="$1" msg="$2"
 | |
|     [ -d "$mwdir/.git" ] || return 0
 | |
| 
 | |
|     local -a __newfiles __modfiles
 | |
|     [ -n "$3" ] && array_copy __newfiles "$3"
 | |
|     array_map __newfiles __strip_mwdir
 | |
|     [ -n "$4" ] && array_copy __modfiles "$4"
 | |
|     array_map __modfiles __strip_mwdir
 | |
| 
 | |
|     cwd="$(pwd)"
 | |
|     cd "$mwdir"
 | |
|     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 init_help() {
 | |
|     uecho
 | |
| }
 | |
| function __init_exportfile() {
 | |
|     local file="$1"
 | |
|     local md5="$(echo -n "$file" | md5sum)"
 | |
|     local url="$MWSITEURL/images/${md5:0:1}/${md5:0:2}/$file"
 | |
|     mkdir -p _media
 | |
|     curl -sko "_media/$file" "$url" 
 | |
| }
 | |
| function __init_exportpage() {
 | |
|     local page_id="$1" page_title="$2"
 | |
|     local rev_user="$3" rev_user_text="$4" rev_id="$5" rev_sha1="$6"
 | |
|     local text_flags="$7" text_content="$8"
 | |
|     estep "$page_title"
 | |
|     echo "# -*- coding: utf-8 mode: text -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| 
 | |
| $text_content" >"$page_title.txt"
 | |
|     [ -f .mwpages ] || touch .mwpages
 | |
|     [ -s .mwpages ] || echo "title,pageid,revid,hash" >.mwpages
 | |
|     echo "\"${page_title//\"/\\\"}\",$page_id,$rev_id,$rev_sha1" >>.mwpages
 | |
| }
 | |
| function init_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir force
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with init_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         --force force=1 \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     [ -n "$mwdir" ] || mwdir=.
 | |
|     if [ ! -d "$mwdir" ]; then
 | |
|         ewarn "Le répertoire $mwdir n'existe pas"
 | |
|         ask_yesno "Voulez-vous le créer?" O || die
 | |
|         mkdir -p "$mwdir" || die
 | |
|     fi
 | |
|     if check_mwdir "$mwdir" && [ -z "$force" ]; then
 | |
|         eerror "Ce répertoire est déjà un export de MediaWiki. Utiliser --force"
 | |
|         return 1
 | |
|     fi
 | |
|     if ! check_mwdir "$mwdir"; then
 | |
|         ask_yesno "$mwdir n'est pas un répertoire de mediawiki. Voulez-vous le configurer?" O || die
 | |
|         estep "Configuration de l'accès à la base de données"
 | |
|         read_value "Hôte du serveur MySQL" MWDBHOST localhost
 | |
|         read_value "Port du serveur MySQL" MWDBPORT 3306
 | |
|         read_value "Compte utilisateur" MWDBUSER "$USER"
 | |
|         read_password "Mot de passe" MWDBPASS "" N
 | |
|         read_value "Nom de la base de données" MWDBNAME
 | |
|         read_value "Préfixe pour les tables" MWPREFIX "" N
 | |
|         estep "Configuration de l'accès au site"
 | |
|         read_value "URL du site MediaWiki" MWSITEURL http://localhost/mediawiki
 | |
|         local var
 | |
|         for var in MWDBHOST MWDBPORT MWDBUSER MWDBPASS MWDBNAME MWPREFIX MWSITEURL; do
 | |
|             set_var_cmd "$var" "${!var}" >>"$mwdir/.mediawiki"
 | |
|         done
 | |
|     fi
 | |
| 
 | |
|     __ensure_mwdir
 | |
|     cd "$mwdir"
 | |
| 
 | |
|     >.mwpages
 | |
|     etitle "Export des images" \
 | |
|         eval "$(mwexportfiles | awkcsv -n -e '{
 | |
|   print "__init_exportfile " quote_value(get("page_title"))
 | |
| }' -a '')"
 | |
|     etitle "Export des pages" \
 | |
|         eval "$(mwexportpages | awkcsv -e '{
 | |
|   page_id = get("page_id")
 | |
|   page_title = get("page_title")
 | |
|   rev_user = get("rev_user")
 | |
|   rev_user_text = get("rev_user_text")
 | |
|   rev_id = get("rev_id")
 | |
|   rev_sha1 = get("rev_sha1")
 | |
|   text_flags = get("text_flags")
 | |
|   if (text_flags != "utf-8") continue
 | |
|   text_content = get("text_content")
 | |
|   gsub(/\\n/, "\n", text_content)
 | |
|   print "__init_exportpage " quote_value(page_id) " " quote_value(page_title) " " quote_value(rev_user) " " quote_value(rev_user_text) " " quote_value(rev_id) " " quote_value(rev_sha1) " " quote_value(text_flags) " " quote_value(text_content)
 | |
| }' -a '')"
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| function newpage_help() {
 | |
|     uecho "$scriptname newpage: créer une nouvelle page de wiki
 | |
| 
 | |
| USAGE
 | |
|     $scriptname newpage titre [-n nom]
 | |
| 
 | |
| - titre est le titre de la nouvelle page utilisé pour créer le contenu initial.
 | |
| - nom est le nom de base du fichier sur disque (utilisé aussi comme titre de la
 | |
|   page dans la base de données). Il est calculé à partir de titre.
 | |
| Ces valeurs peuvent être spécifiées individuellement.
 | |
| 
 | |
| OPTIONS
 | |
|     -d MWDIR
 | |
|         Spécifier le répertoire du mediawiki
 | |
|     -n NOM
 | |
|         Forcer le nom de base du fichier à utiliser au lieu de le calculer à
 | |
|         partir de titre.
 | |
|     --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 MWCOMMIT=1, ne
 | |
|         pas lancer l'enregistrement des modifications dans le gestionnaire de
 | |
|         version."
 | |
| }
 | |
| function newpage_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir title log
 | |
|     local edit=1
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with newpage_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         -n:,--name:,-t:,--title: name= \
 | |
|         -l,--log log=1 \
 | |
|         -c,--noedit edit= \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     __ensure_mwdir
 | |
|     in_mwdir || cd "$mwdir"
 | |
|     
 | |
|     title="$1"
 | |
|     if [ -z "$title" -a -z "$log" ]; then
 | |
|         read_value "Veuillez entrer un titre pour la page de wiki à créer" title
 | |
|     fi
 | |
| 
 | |
|     if [ -n "$name" ]; then
 | |
|         name="${name%.txt}"
 | |
|     else
 | |
|         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 base de la page" name "$name"
 | |
| 
 | |
|     local basename="$name"
 | |
|     local basefile="$name"
 | |
|     local file="$basefile.txt"
 | |
| 
 | |
|     if __check_exists "$file"; then
 | |
|         estepw "Le fichier $(ppath "$file") existe déjà."
 | |
|         ask_yesno "Si vous continuez, un ${COULEUR_JAUNE}NOUVEAU fichier${COULEUR_NORMALE} avec un suffixe numérique sera créé.
 | |
| Sinon, vous pouvez utiliser '$scriptname edit' pour modifier le fichier existant.
 | |
| Voulez-vous continuer?" N || return 1
 | |
|     fi
 | |
|     local i=0
 | |
|     while __check_exists "$file"; do
 | |
|         i=$(($i + 1))
 | |
|         name="$basename-$i"
 | |
|         file="$basefile-$i.txt"
 | |
|     done
 | |
|     mkdirof "$file"
 | |
| 
 | |
|     local -a newfiles modfiles
 | |
|     __create "$mwdir" "$file" "$name" "$title" newfiles modfiles || return
 | |
|     if [ -n "$edit" -a -n "$MWCOMMIT" ]; then
 | |
|         __commit "$mwdir" "newpage $title --> $name" newfiles modfiles || return
 | |
|     else
 | |
|         estepi "mwci $(quoted_args "mwci newpage $title --> $name")"
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| function find_help() {
 | |
|     uecho "$scriptname find: trouver une page
 | |
| 
 | |
| USAGE
 | |
|     $scriptname find <filtre>
 | |
| 
 | |
| OPTIONS
 | |
|     -d MWDIR
 | |
|         Spécifier le répertoire de mediawiki"
 | |
| }
 | |
| function find_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with find_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     __ensure_mwdir
 | |
| 
 | |
|     local filter="$1"
 | |
|     find "$mwdir" -type f -name "*.txt" |
 | |
|     sed "s#^$mwdir/##g; s#.txt\$##g" |
 | |
|     csort | {
 | |
|         if [ -n "$filter" ]; then
 | |
|             grep -i "$filter"
 | |
|         else
 | |
|             cat
 | |
|         fi
 | |
|     }
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| function edit_help() {
 | |
|     uecho "$scriptname edit: modifier une page
 | |
| 
 | |
| USAGE
 | |
|     $scriptname edit <filtre>
 | |
| 
 | |
| OPTIONS
 | |
|     -d MWDIR
 | |
|         Spécifier le répertoire de mediawiki"
 | |
| }
 | |
| function edit_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with edit_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     __ensure_mwdir
 | |
| 
 | |
|     local filter="$1" found=
 | |
|     if [ -f "$filter" ]; then
 | |
|         local file="$(abspath "$filter")"
 | |
|         if [ "${file#$mwdir/}" != "$file" -a "${file%.txt}" != "$file" ]; then
 | |
|             page="${file#$mwdir/}"
 | |
|             page="${page%.txt}"
 | |
|             found=1
 | |
|         fi
 | |
|     fi
 | |
|     if [ -z "$found" ]; then
 | |
|         local -a pages
 | |
|         array_from_lines pages "$(find_cmd -qq -d "$mwdir" "$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}" "$mwdir/$page.txt"
 | |
|     array_add modfiles "$mwdir/$page.txt"
 | |
| 
 | |
|     if [ -n "$MWCOMMIT" ]; then
 | |
|         __commit "$mwdir" "edit ${page//\//:}" newfiles modfiles || return
 | |
|     else
 | |
|         estepi "mwci $(quoted_args "edit ${page//\//:}")"
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| function commit_help() {
 | |
|     uecho "$scriptname commit: enregistrer les modifications dans le gestionnaire de version
 | |
| 
 | |
| USAGE
 | |
|     $scriptname commit <msg>
 | |
| 
 | |
| OPTIONS
 | |
|     -d MWDIR
 | |
|         Spécifier le répertoire de mediawiki"
 | |
| }
 | |
| function commit_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with commit_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     __ensure_mwdir
 | |
|     __commit "$mwdir" "$*" || return
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| function sync_help() {
 | |
|     uecho "$scriptname sync: synchroniser les fichiers vers la base de données
 | |
| 
 | |
| USAGE
 | |
|     $scriptname sync [destdir]
 | |
| 
 | |
| OPTIONS
 | |
|     -d MWDIR
 | |
|         Spécifier le répertoire du mediawiki local"
 | |
| }
 | |
| 
 | |
| __SYNC_HEADERS="\
 | |
| fs_title,fs_path,fs_hash,fs_doublon\
 | |
| ,local_title,local_pageid,local_revid,local_hash\
 | |
| ,remote_pageid,remote_title,remote_revid,remote_hash,remote_content\
 | |
| ,etat,action\
 | |
| "
 | |
| 
 | |
| function __sync_action_fixme() {
 | |
|     eerror "Une ligne n'a pas pu être traitée. C'est probablement un bug
 | |
| $__SYNC_HEADERS
 | |
| $1"
 | |
| }
 | |
| function __sync_action_ignore() {
 | |
|     :
 | |
| }
 | |
| function __sync_action_create_local() {
 | |
|     local pageid="${9}" title="${10}" revid="${11}" hash="${12}"
 | |
|     local content="${13}"
 | |
|     content="${content//\\n/
 | |
| }"
 | |
| 
 | |
|     local file="$mwdir/$title.txt"
 | |
|     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
 | |
| 
 | |
| $content" >"$file"
 | |
|     #echo "\"${title//\"/\\\"}\",$pageid,$revid,$hash" >>"$mwdir/.mwpages" #XXX
 | |
|     #[ -n "$__newfiles" ] && array_add "$__newfiles" "$file"
 | |
|     #[ -n "$__modfiles" ] && array_add "$__modfiles" "$mwdir/.mwpages"
 | |
| }
 | |
| function __sync_action_create_remote() {
 | |
|     :
 | |
| }
 | |
| function __sync_action_update_remote() {
 | |
|     :
 | |
| }
 | |
| function __sync_action_resolve() {
 | |
|     :
 | |
| }
 | |
| 
 | |
| function __sync_ac_clean() {
 | |
|     ac_clean "$tmpinfos" "$fsinfos" "$dblinfos" "$localinfos" "$remoteinfos" "$mergedinfos"
 | |
| }
 | |
| 
 | |
| function sync_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir destdir noconf
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with sync_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     __ensure_mwdir
 | |
| 
 | |
|     local tmpinfos; ac_set_tmpfile tmpinfos
 | |
| 
 | |
|     ### Informations du système de fichier local
 | |
|     etitle "Système de fichier local"
 | |
|     local fsinfos; ac_set_tmpfile fsinfos
 | |
| 
 | |
|     estep "Calcul des informations"
 | |
|     find "$mwdir" -path "$mwdir/.git" -prune -o \
 | |
|         -type d -name .svn -prune -o \
 | |
|         -type f -name "*.txt" -print |
 | |
|     "$scriptdir/lib/b36sha1.py" --skip --mediawiki "$mwdir" \
 | |
|         >"$tmpinfos"
 | |
| 
 | |
|     # Supprimer les doublons
 | |
|     # dblinfos contient la liste des fichiers en doublon
 | |
|     estep "Analyse des doublons"
 | |
|     local dblinfos; ac_set_tmpfile dblinfos
 | |
|     sortcsv -k title "$tmpinfos" |
 | |
|     awkcsv -v prevtitle= -v prevline= -v firstdbl:int=1 \
 | |
|         -v dblinfos="$dblinfos" \
 | |
|         -e '{
 | |
|   title = get("title")
 | |
|   if (prevtitle != "") {
 | |
|     if (title != prevtitle) {
 | |
|       if (firstdbl) { # pour eviter d"afficher le dernier doublon
 | |
|         printheaders()
 | |
|         print prevline
 | |
|       }
 | |
|       firstdbl = 1
 | |
|     } else {
 | |
|       if (do_once("dbl-show-headers")) {
 | |
|         array_printcsv(HEADERS, dblinfos)
 | |
|       }
 | |
|       if (firstdbl) {
 | |
|         firstdbl = 0
 | |
|         printto(prevline, dblinfos)
 | |
| 
 | |
|         printheaders()
 | |
|         array_parsecsv(fields, prevline)
 | |
|         fields[geth("doublon")] = "1"
 | |
|         array_printcsv(fields)
 | |
|       }
 | |
|       printcsv(dblinfos)
 | |
|     }
 | |
|   }
 | |
|   formatcsv()
 | |
|   prevtitle = title
 | |
|   prevline = $0
 | |
| }' -a ' END {
 | |
|   if (prevtitle != "" && firstdbl) {
 | |
|     printheaders()
 | |
|     print prevline
 | |
|   }
 | |
| }' >"$fsinfos"
 | |
| 
 | |
|     if [ -s "$dblinfos" ]; then
 | |
|         eerror "Vous avez des fichiers en doublon. Ces fichiers seront ignorés"
 | |
|         awkcsv <"$dblinfos" -e '{ print "! " get("path") }' -a ''
 | |
|     fi
 | |
| 
 | |
|     #echo === fsinfos; cat "$fsinfos" #XXX
 | |
|     eend
 | |
| 
 | |
|     ### Informations de la base de données locale
 | |
|     etitle "Base de données locale"
 | |
|     local localinfos; localinfos="$mwdir/.mwpages"
 | |
| 
 | |
|     #echo === localinfos; cat "$localinfos" #XXX
 | |
|     eend
 | |
| 
 | |
|     ### Informations de la base de données distante
 | |
|     etitle "Base de données distante"
 | |
|     local remoteinfos; ac_set_tmpfile remoteinfos
 | |
| 
 | |
|     mwexportpages | awkcsv -e '{
 | |
|   # ne garder que les texte que l"on peut récupérer
 | |
|   text_flags = get("text_flags")
 | |
|   if (text_flags != "utf-8") next
 | |
| }' | awkcsv \
 | |
|     -m title:page_title,pageid:page_id,revid:rev_id,hash:rev_sha1,content:text_content \
 | |
|     -k title,pageid,revid,hash,content \
 | |
|     >"$remoteinfos"
 | |
| 
 | |
|     #echo === remoteinfos; cat "$remoteinfos" #XXX
 | |
|     eend
 | |
| 
 | |
|     ### Faire le rapprochement
 | |
|     etitle "Rapprochement des informations"
 | |
|     local mergedinfos; ac_set_tmpfile mergedinfos
 | |
| 
 | |
|     estep "Fusion des fichiers"
 | |
|     #XXX corriger la fusion des fichiers avec un script externe en python. le
 | |
|     # problème est la fusion de fs avec remote en cas de non existence de local
 | |
|     mergecsv -k title --lprefix fs_ "$fsinfos" --rprefix local_ "$localinfos" >"$tmpinfos"
 | |
|     mergecsv --lk local_title "$tmpinfos" --rk title --rprefix remote_ "$remoteinfos" |
 | |
|     awkcsv -k '*,etat,action' >"$mergedinfos"
 | |
| 
 | |
|     estep "Calcul des actions"
 | |
|     awkcsv <"$mergedinfos" -e '
 | |
| function toint(v,            i) {
 | |
|   i = int(v + 0)
 | |
|   return i
 | |
| }
 | |
| function setea(etat, action) {
 | |
|   set("etat", etat)
 | |
|   set("action", action)
 | |
| }
 | |
| function setfixme() {
 | |
|   setea("@", "fixme")
 | |
| }
 | |
| 
 | |
| {
 | |
|   fs_title = get("fs_title")
 | |
|   local_title = get("local_title")
 | |
|   remote_title = get("remote_title")
 | |
| 
 | |
|   ## traiter d"abord les fichiers à problème
 | |
|   # doublons
 | |
|   if (get("fs_doublon") != "") {
 | |
|     setea("%", "ignore")
 | |
|   }
 | |
| 
 | |
|   # fichiers perdus
 | |
|   else if (local_title != "" && fs_title == "") {
 | |
|     setea("!", "ignore")
 | |
|   }
 | |
| 
 | |
|   # fichiers gênants
 | |
|   else if (fs_title != "" && remote_title != "" && local_title == "") {
 | |
|     setea("~", "ignore")
 | |
|   }
 | |
| 
 | |
|   if (get("action") == "") {
 | |
|     # etats incohérents
 | |
|     fs_hash = get("fs_hash")
 | |
|     local_pageid = get("local_pageid")
 | |
|     local_revid = get("local_revid")
 | |
|     local_hash = get("local_hash")
 | |
|     remote_pageid = get("remote_pageid")
 | |
|     remote_revid = get("remote_revid")
 | |
|     remote_hash = get("remote_hash")
 | |
|     if (local_pageid == remote_pageid && local_revid == remote_revid && \
 | |
|         local_hash != remote_hash) {
 | |
|       #XXX avertir utilisateur
 | |
|       local_hash = remote_hash
 | |
|       set("local_hash", remote_hash)
 | |
|     }
 | |
| 
 | |
|   ## puis traiter les états standards
 | |
|     # notregistered
 | |
|     if (fs_title != "" && local_title == "" && remote_title == "") {
 | |
|       setea("?", "ignore")
 | |
|     }
 | |
| 
 | |
|     # localnew
 | |
|     else if (fs_title != "" && fs_title == local_title && remote_title == "") {
 | |
|       setea("A", "create_remote")
 | |
|     }
 | |
| 
 | |
|     # remotenew
 | |
|     else if (fs_title == "" && local_title == local_title && remote_title != "") {
 | |
|       setea("N", "create_local")
 | |
|     }
 | |
| 
 | |
|     else if (fs_title != "" && fs_title == local_title && local_title == remote_title && \
 | |
|              local_pageid == remote_pageid) {
 | |
|       # bothsame
 | |
|       if (local_revid == remote_revid && fs_hash == local_hash) {
 | |
|         setea("", "ignore")
 | |
|       }
 | |
| 
 | |
|       # localmodified
 | |
|       else if (local_revid == remote_revid && fs_hash != local_hash) {
 | |
|         setea("M", "update_remote")
 | |
|       }
 | |
| 
 | |
|       # remotemodified
 | |
|       else if (toint(remote_revid) > toint(local_revid) && fs_hash == local_hash) {
 | |
|         setea("U", "create_local")
 | |
|       }
 | |
| 
 | |
|       # bothconflict
 | |
|       else if (toint(remote_revid) > toint(local_revid) && fs_hash != local_hash) {
 | |
|         setea("C", "resolve")
 | |
|       }
 | |
| 
 | |
|       # inconnu
 | |
|       else {
 | |
|         setfixme()
 | |
|       }
 | |
|     } else {
 | |
|       setfixme()
 | |
|     }
 | |
|   }
 | |
| }' >"$tmpinfos"
 | |
|     cat "$tmpinfos" >"$mergedinfos"
 | |
| 
 | |
|     # Afficher les resources dans un état spécial qui seront ignorées
 | |
|     awkcsv <"$mergedinfos" -e '{
 | |
|   etat = get("etat")
 | |
|   action = get("action")
 | |
|   if (!etat || action != "ignore") next
 | |
| 
 | |
|   title = get("fs_path")
 | |
|   if (! title) title = get("local_title")
 | |
|   if (! title) title = get("remote_title")
 | |
|   print etat " " title
 | |
| }' -a ''
 | |
| 
 | |
|     # Calculer les resources qui devront être traitées
 | |
|     awkcsv <"$mergedinfos" -e '{
 | |
|   etat = get("etat")
 | |
|   action = get("action")
 | |
|   if (!etat || action == "ignore") next
 | |
| 
 | |
|   title = get("fs_path")
 | |
|   if (! title) title = get("local_title")
 | |
|   if (! title) title = get("remote_title")
 | |
|   print etat " " title
 | |
| }' -a '' >"$tmpinfos"
 | |
| 
 | |
|     if [ ! -s "$tmpinfos" ]; then
 | |
|         estepi "Aucune modification à effectuer"
 | |
|         __sync_ac_clean
 | |
|         return 0
 | |
|     fi
 | |
|     eend
 | |
| 
 | |
|     etitle "Synchronisation"
 | |
|     cat "$tmpinfos"
 | |
| 
 | |
|     if ask_yesno "Voulez-vous appliquer les modifications?" O; then
 | |
|         eval "$(awkcsv <"$mergedinfos" -e '{
 | |
|   print "__sync_action_" get("action") " " quoted_values()
 | |
| }' -a '')"
 | |
|     fi
 | |
| 
 | |
|     eend
 | |
| 
 | |
|     __sync_ac_clean
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| function generate_help() {
 | |
|     uecho "$scriptname generate: Générer la documentation d'un projet
 | |
| 
 | |
| USAGE
 | |
|     $scriptname generate [options] srcdir
 | |
| 
 | |
| Si srcdir contient un fichier .mediawikigen, ce fichier est sourcé pour générer
 | |
| la documentation. Les fonction setpage() et addpage() sont disponible.
 | |
| 
 | |
| OPTIONS
 | |
|     -d MWDIR
 | |
|         Spécifier le répertoire du mediawiki"
 | |
| }
 | |
| function generate_cmd() {
 | |
|     eval "$(utools_local; mw_local)"
 | |
|     local mwdir title
 | |
|     parse_opts "${PRETTYOPTS[@]}" \
 | |
|         --help '$exit_with generate_help' \
 | |
|         -d:,--mwdir: mwdir= \
 | |
|         -t:,--title: title= \
 | |
|         @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
|     __ensure_mwdir
 | |
| 
 | |
|     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 "$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 "$mwdir")/${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 "$mwdir")/${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}' <README.txt
 | |
|                 echo
 | |
|             } | addpage start
 | |
|         fi
 | |
|         
 | |
|         local -a cmds
 | |
|         local first cmd cmdname
 | |
|         etitle "Documentation des outils"
 | |
|         array_lsfiles cmds .
 | |
|         first=1
 | |
|         for cmd in "${cmds[@]}"; do
 | |
|             cmdname="$(basename "$cmd")"
 | |
|             [ -x "$cmd" ] || continue
 | |
|             {
 | |
|                 echo "===== $cmdname ====="
 | |
|                 echo "<code>"
 | |
|                 "$cmd" --help
 | |
|                 echo "</code>"
 | |
|             } | 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 .mediawikigen ]; then
 | |
|             ./.mediawikigen
 | |
|         elif [ -f .mediawikigen ]; then
 | |
|             source ./.mediawikigen
 | |
|         else
 | |
|             gendefault
 | |
|         fi
 | |
|         array_from_lines newfiles "$(<"$newfiles")"
 | |
|         array_from_lines modfiles "$(<"$modfiles")"
 | |
|         if [ -n "$MWCOMMIT" ]; then
 | |
|             __commit "$mwdir" "generate $srcdir" newfiles modfiles
 | |
|         else
 | |
|             estepi "mwci $(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;;
 | |
| init) init_cmd "$@";;
 | |
| 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 "$@";;
 | |
| __mwmysql) #XXX faire une requête SQL sur la base de données
 | |
|     __ensure_mwdir
 | |
|     mwmysql "$@"
 | |
|     ;;
 | |
| *) die "$cmd: commande incorrecte";;
 | |
| esac
 |