#!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 function display_help() { uecho "$scriptname: gestion d'une distribution upstream Des fichiers de configuration (par exemple) sont distribués par un partenaire, et il faut maintenir des modifications locales, tout en acceptant les mises à jour provenant de l'upstream. Ce script aide à maintenir un tel scénario. En général, la distribution upstream identifie les fichiers modifiables en leur donnant une extension particulière, par exemple 'file.origine' ou 'file.default' La liste des extensions reconnues est spécifiée avec l'option -s. Lors de leur intégration dans le répertoire local, ces fichiers sont copiés sans cette extension. Terminologie: Les fichiers pour lesquels il faut maintenir une version locale sont appelés 'fichiers locaux', qu'ils viennent de la distribution upstream ou non. Les autres fichiers qui proviennent de la distribution sont appelés 'fichiers upstream'. USAGE $scriptname cmd [options] OPTIONS COMMUNES -s .EXT Ajouter une extension à la liste des extensions reconnues comme contenu original modifiable dans la distribution upstream. Par défaut, les extensions suivantes sont reconnues: ${DEFAULT_ORIGEXTS[*]} Cette option peut être utilisée autant de fois que nécessaire. --clear-origexts Supprimer la liste par défaut des extensions origines. Cette option doit être spécifiée avant l'option -s pour construire une nouvelle liste. La liste des extensions ne doit pas être vide. Si c'est le cas, elle est modifiée pour contenir l'unique élément (.$ORIGEXT) -d WORKDIR Spécifier le répertoire de travail. Par défaut, la racine du répertoire de travail est cherchée à partir du répertoire courant. --help Afficher l'aide détaillée de la commande spécifiée COMMANDES init [WORKDIR [ARCHIVE]] Initialiser un répertoire de travail pour contenir une distribution upstream upstream-new, new SRCDIR|ARCHIVE [WORKDIR] Intégrer une nouvelle distribution upstream. Les nouveaux fichiers sont copiés tout de suite dans le répertoire de travail. Par contre, les modifications ne sont intégrées qu'avec la commande patch upstream-clear, clear [WORKDIR] Supprimer tous les fichiers non modifiés de l'upstream. local-create, create FILE Créer et/ou identifier FILE comme une modification locale par rapport à l'upstream. local-edit, edit FILE S'assurer que local-create a été exécuté si nécessaire pour FILE, puis l'éditer avec $EDITOR local-copy, cp SRCFILE DESTFILE local-move, mv SRCFILE DESTFILE local-remove, rm FILE Frontend pour respectivement cp, mv et rm. Ces commandes agissent aussi sur les fichiers orig et de tag. local-tag, tag FILE TAG Faire une copie du fichier local avec le tag spécifié. Si le fichier de tag existe déjà, il est écrasé. local-switch, switch TAG FILE Sélectionner la copie avec le tag spécifié. local-put, put [WORKDIR] DESTDIR Copier tous les fichiers locaux dans DESTDIR, par exemple pour faire une sauvegarde. Si DESTDIR n'est pas spécifié, prendre la valeur de l'origine, affichée par local-list local-get, get [-l|-s] SRCDIR [WORKDIR] Opération inverse de local-put: intégrer tous les fichiers de SRCDIR comme fichiers locaux. Si SRCDIR n'est pas spécifié, prendre la valeur de l'origine, affichée par local-list local-list, list [WORKDIR] Lister tous les fichiers locaux. Les fichiers pour lesquels il faut intégrer une modification de l'upstream avec la commande local-patch sont identifiés visuellement. upstream-diff, udiff [FILE] Après intégration d'une nouvelle distribution upstream, afficher les modifications entre la nouvelle distribution upstream et l'ancienne pour tous les fichiers modifiables local-diff, ldiff [FILE] Afficher les modifications locales par rapport à l'upstream pour le(s) fichier(s) spécifié(s). local-patch, lpatch [FILE] Après intégration d'une nouvelle distribution upstream, appliquer au(x) le(s) fichier(s) spécifié(s) les modifications disponibles affichées par upstream-diff. local-forget, lforget [FILE] Après intégration d'une nouvelle distribution upstream, oublier les modifications disponibles pour le(s) fichier(s) spécifié(s)." } SCRIPT_ALIASES=(#alias:command udn:upstream-new udc:local-create ude:local-edit uds:local-switch udl:local-list udd:local-diff udp:local-patch ) CMD_ALIASES=( unew:upstream-new new:upstream-new uclear:upstream-clear clear:upstream-clear udiff:upstream-diff lc:local-create lcreate:local-create c:local-create create:local-create le:local-edit ledit:local-edit e:local-edit edit:local-edit cp:local-copy copy:local-copy mv:local-move move:local-move rm:local-remove remove:local-remove delete:local-remove del:local-remove lt:local-tag ltag:local-tag t:local-tag tag:local-tag lswitch:local-switch s:local-switch sw:local-switch switch:local-switch lput:local-put put:local-put push:local-put lget:local-get get:local-get pull:local-get link:"local-get -l" ln:"local-get -l" ll:local-list llist:local-list list:local-list ls:local-list l:local-list ldiff:local-diff diff:local-diff lpatch:local-patch patch:local-patch lforget:local-forget forget:local-forget ) DEFAULT_CMD=local-list ORIGEXT=udist DEFAULT_ORIGEXTS=(".$ORIGEXT" .origine .default) ORIGEXTS=("${DEFAULT_ORIGEXTS[@]}") 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")/lib/ulib/auto" || exit 1 urequire conf install INSTALL_VERBOSE= INSTALL_USES_PPATH=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=udist break fi done [ -n "$EDITOR" ] || EDITOR=vi UDISTOPTS=( -s:,--ext:,--origext: '$add@ ORIGEXTS' --clear-origexts '$ORIGEXTS=()' -d:,--workdir: workdir= ) # Terminologie utilisée dans le code: # - un fichier default est un fichier de la distribution upstream ayant une des # extensions du tableau ORIGEXTS, ce qui en fait un candidat automatique pour # avoir une copie locale. Les fichiers default sont de la forme 'NAME.origext' # - un fichier local est un fichier auquel est associé un fichier orig. Les # fichier locaux sont de la forme 'NAME'. En général, un fichier local a un # fichier default correspondant dans la distribution upstream. # - un fichier orig est la copie originale d'un fichier de la distribution # upstream. Ce fichier est associé à un fichier local qui contient ses # modifications locales. Les fichiers orig sont versionnés tant qu'ils ne sont # pas intégrés et sont de la forme '.--NAME--[version].udist' # - un fichier de tag est un fichier associé à un fichier local et qui a un tag # associé. Ceci permet de maintenir plusieurs "versions" d'un même fichier # local, e.g. "dev", "prod", etc. function udist_local() { utools_local echo "local workdir" } function __check_workdir() { [ -f "$1/.udist" ] } function find_workdir() { local workdir="$(abspath "${1:-.}")" while [ "$workdir" != "/" ]; do if __check_workdir "$workdir"; then echo "$workdir" return 0 fi workdir="$(dirname "$workdir")" done return 1 } function __after_parse() { array_fix_paths ORIGEXTS [ -n "${ORIGEXTS[*]}" ] || ORIGEXTS=(".$ORIGEXT") if [ "$1" != "initial" ]; then [ -z "$workdir" -o -d "$workdir" ] || die "$workdir: répertoire introuvable" workdir="$(find_workdir "$workdir")" || die "Impossible de trouver le répertoire de travail. Faut-il faire '$scriptname init'?" workdir="$(abspath "$workdir")" fi } function __udist_initial() { echo "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 VERSION= VERSIONS=() TAGS=() ORIGIN= LOCALS=()" } function __udist_locals() { # afficher les variables définies dans le fichier .udist echo "local VERSION ORIGIN; local -a VERSIONS TAGS LOCALS" } function __load_udist_nolocal() { ( # charger le fichier .udist ($1) et affiche les commandes pour définir les # variables PVERSION, PVERSIONS, PTAGS, PORIGIN, PLOCALS. # P ($2) est un préfixe éventuel pour le nom des variables VERSION=; VERSIONS=(); TAGS=(); ORIGIN=; LOCALS=() local udistf="${1:-$workdir}" [ -d "$udistf" ] && udistf="$udistf/.udist" source "$udistf" echo_setv "${2}VERSION" "$VERSION" set_array_cmd "${2}VERSIONS" VERSIONS set_array_cmd "${2}TAGS" TAGS echo_setv "${2}ORIGIN" "$ORIGIN" set_array_cmd "${2}LOCALS" LOCALS ); } function __load_udist() { __udist_locals __load_udist_nolocal "$@" } function __save_udist() { # écrire dans le fichier .udist ($1) les variables spécifiées, parmi # VERSION, VERSIONS, TAGS, ORIGIN, LOCALS. Les arguments sont de la forme # DEST[:varname], e.g. # __save_udist .udist VERSION:value ORIGIN # qui met à jour VERSION avec $value et ORIGIN avec $ORIGIN local __su_udistf="${1:-$workdir}"; shift [ -d "$__su_udistf" ] && __su_udistf="$__su_udistf/.udist" local __su_part __su_dest __su_varname local -a __su_cmd __su_cmd=(conf_enable "$__su_udistf") for __su_dest in "$@"; do splitpair "$__su_dest" __su_dest __su_varname [ -n "$__su_varname" ] || __su_varname="$__su_dest" case "$__su_dest" in VERSION) array_add __su_cmd "$(echo_setv VERSION "${!__su_varname}")";; VERSIONS) array_add __su_cmd "$(set_array_cmd VERSIONS "${__su_varname}")";; TAGS) array_add __su_cmd "$(set_array_cmd TAGS "${__su_varname}")";; ORIGIN) array_add __su_cmd "$(echo_setv ORIGIN "${!__su_varname}")";; LOCALS) array_add __su_cmd "$(set_array_cmd LOCALS "${__su_varname}")";; esac done "${__su_cmd[@]}" } function __is_default() { # tester si $1 est un fichier de la forme name.origext local origext ufile lfile for origext in "${ORIGEXTS[@]}"; do ufile="$1" lfile="${ufile%$origext}" [ "$ufile" != "$lfile" ] && return 0 done return 1 } function __get_local() { # tester si $1 est un fichier de la form 'NAME.origext'. Dans ce cas, # afficher 'NAME'. Sinon, afficher la valeur inchangée. # note: cette fonction fait la même chose que __is_default, sauf qu'elle # affiche le nom local correspondant au nom upstream local origext ufile lfile for origext in "${ORIGEXTS[@]}"; do ufile="$1" lfile="${ufile%$origext}" [ "$ufile" != "$lfile" ] && { echo "$lfile" return 0 } done echo "$1" return 1 } function __get_orig() { # obtenir le fichier orig correspondant à $1, i.e. afficher .--NAME--.udist # pour $1==NAME local dir="$(dirname "$1")" name="$(basename "$1")" echo "$dir/.--$name--.$ORIGEXT" } function __list_localfiles() { # lister les fichiers origs du répertoire $1 et en dériver une liste triée # de *noms* de fichiers locaux cd "$1"; find -name ".--*--*.$ORIGEXT" | filter_vcspath | while read path; do dir="$(dirname "$path")" file="$(basename "$path")" file="${file#.--}" file="${file%--*.$ORIGEXT}" path="$dir/$file" path="${path#./}" echo "$path" done | csort -u } function __list_tagfiles() { # lister les *noms* des fichiers de tag correspondant au fichier local $1 local dir="$(dirname "$1")" name="$(basename "$1")" list_all "$dir" "$name.%*" } function __list_origfiles() { # afficher les *noms* des fichiers origs correspondant au fichier local $1 local dir="$(dirname "$1")" name="$(basename "$1")" list_all "$dir" ".--$name--*.$ORIGEXT" } function __get_version() { # afficher la version correspondant au fichier orig $1 local version="$(basename "$1")" version="${version##*--}" version="${version%.$ORIGEXT}" echo "$version" } function __norm_ctag() { # normaliser le tag composite $1: les doublons sont supprimés, et les tags # sont triés local -a tags array_split tags "$1" % array_from_lines tags "$(array_to_lines tags | csort -u)" array_join tags % } function __get_ctag() { # afficher le tag composite normalisé du fichier de tag $1. chaque tag est # séparé par % local tags="$(basename "$1")" tags="${tags##*.%}" tags="${tags%\%}" __norm_ctag "$tags" } function __init_tags() { # initialiser le tableau $1(=tags) avec la liste des tags du fichier de tag $2 array_split "${1:-tags}" "$(__get_ctag "$2")" % } function __get_tagfile() { # afficher le nom du fichier de tag correspondant au fichier local $1 et au # tag $2 (qui doit avoir été normalisé). $3(=tagfiles) est le cas échéant le # nom du tableau contenant la liste des fichiers de tags. local localfile="$1" ctag="$2" local localdir="$(dirname "$localfile")" if [ -n "$3" -a "$3" != "tagfiles" ]; then local -a tagfiles array_copy tagfiles "$3" fi for tagfile in "${tagfiles[@]}"; do curtag="$(__get_ctag "$tagfile")" if [ "$curtag" == "$ctag" ]; then echo "$tagfile" return 0 fi done return 1 } function __get_curtagfile() { # afficher le nom du fichier de tag *courant* correspondant au fichier local # $1. $2(=tagfiles) est le cas échéant le nom du tableau contenant la liste # des fichiers de tags local localfile="$1" local localdir="$(dirname "$localfile")" if [ -n "$3" -a "$3" != "tagfiles" ]; then local -a tagfiles array_copy tagfiles "$3" fi for tagfile in "${tagfiles[@]}"; do if testsame "$localfile" "$localdir/$tagfile"; then echo "$tagfile" return 0 fi done return 1 } function is_local() { # tester si $1 est un fichier modifiable ayant une version originale dans # l'upstream local origext ufile lfile # tester d'abord si c'est un fichier de l'upstream de la forme # 'name.origext' for origext in "${ORIGEXTS[@]}"; do ufile="$1" lfile="${ufile%$origext}" if [ "$ufile" != "$lfile" -a -e "$lfile" ]; then return 0 fi done # ensuite tester si c'est un fichier local de la forme 'name' tel que # 'name.origext' existe for origext in "${ORIGEXTS[@]}"; do lfile="$1" ufile="$lfile$origext" if [ -e "$lfile" -a -e "$ufile" ]; then return 0 fi done return 1 } function get_upstream() { # obtenir le fichier de l'upstream correspondant à $1 local origext ufile lfile # tester d'abord si c'est un fichier de l'upstream de la forme # 'name.origext'. Afficher alors 'name.origext' for origext in "${ORIGEXTS[@]}"; do ufile="$1" lfile="${ufile%$origext}" if [ "$ufile" != "$lfile" -a -e "$lfile" ]; then echo "$ufile" return 0 fi done # ensuite tester si c'est un fichier local de la forme 'name' tel que # 'name.origext' existe. Afficher alors 'name.origext' for origext in "${ORIGEXTS[@]}"; do lfile="$1" ufile="$lfile$origext" if [ -e "$lfile" -a -e "$ufile" ]; then echo "$ufile" return 0 fi done # sinon afficher $1.origext echo "$1${ORIGEXTS[0]}" return 1 } function get_local() { # obtenir le fichier local modifiable correspondant à $1 local origext ufile lfile # tester d'abord si c'est un fichier de l'upstream de la forme # 'name.origext'. Afficher alors 'name' for origext in "${ORIGEXTS[@]}"; do ufile="$1" lfile="${ufile%$origext}" if [ "$ufile" != "$lfile" -a -e "$lfile" ]; then echo "$lfile" return 0 fi done # ensuite tester si c'est un fichier local de la forme 'name' tel que # 'name.origext' existe. Afficher alors 'name' for origext in "${ORIGEXTS[@]}"; do lfile="$1" ufile="$lfile$origext" if [ -e "$lfile" -a -e "$ufile" ]; then echo "$lfile" return 0 fi done # sinon afficher $1 inchangé echo "$1" return 1 } function page_maybe() { if isatty; then less -XF else cat fi } ################################################################################ # template à recopier et adapter pour chaque nouvelle opération function template_help() { uecho "$scriptname template: USAGE $scriptname template [options] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant." } function template_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with template_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" #[ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" __after_parse } ################################################################################ function init_help() { uecho "$scriptname init: initialiser un répertoire de travail USAGE $scriptname init [WORKDIR [ARCHIVE|SRCDIR]] $scriptname init -d WORKDIR [ARCHIVE|SRCDIR]" } function init_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with init_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" array_fix_paths ORIGEXTS [ -n "$workdir" ] || { workdir="${1:-.}"; shift; } workdir="$(abspath "$workdir")" if [ ! -d "$workdir" ]; then ewarn "$(ppath "$workdir"): ce répertoire n'existe pas" ask_yesno "Voulez-vous le créer?" O || die mkdir -p "$workdir" || die fi if [ -f "$workdir/.udist" ]; then estepi "$(ppath "$workdir"): Ce répertoire est déjà initialisé pour udist" else touch "$workdir/.udist" || die __udist_initial >"$workdir/.udist" estepn "$(ppath "$workdir"): répertoire de travail initialisé avec succès" fi local archive="$1"; shift if [ -n "$archive" ]; then upstream_new_cmd -d "$workdir" "$archive" fi } ################################################################################ function __unew_copy() { # copier les fichiers et répertoire de $1 dans $2 en identifiant les # fichiers originaux modifiés avec la version $3 local srcdir="$1" destdir="$2" newversion="$3" osrcdir="$4" odestdir="$5" local -a srcs; local srcname src destname desto destl local s array_lsall srcs "$srcdir" "*" ".*" for src in "${srcs[@]}"; do srcname="$(basename "$src")" desto= # fichier orig destl= # fichier local if [ -f "$src" ]; then #################################################################### # copie d'un fichier if destname="$(__get_local "$srcname")"; then # c'est un fichier default. stratégie: ne jamais écraser le # fichier local & copier le fichier orig la première fois, ou # s'il est différent desto="$destdir/.--$destname--.$ORIGEXT" destl="$destdir/$destname" if [ ! -f "$desto" ]; then mkdirof "$desto" if [ -f "$desto" ]; then if testdiff "$src" "$desto"; then cat "$src" >"$desto"; edot $? "REPL ${src#$osrcdir/} --> ${desto#$odestdir/}" fi else cp_a "$src" "$desto"; edot $? "NEW ${src#$osrcdir/} --> ${desto#$odestdir/}" fi [ -f "$destl" ] || { cp_a "$src" "$destl"; edot $? "NEW ${src#$osrcdir/} --> ${destl#$odestdir/}" } continue fi # si on arrive ici, c'est qu'il y a déjà un fichier orig. else # ce n'est pas un fichier default. stratégie: n'écraser le # fichier local que s'il n'existe pas de fichier orig desto="$destdir/.--$destname--.$ORIGEXT" destl="$destdir/$destname" if [ ! -f "$desto" ]; then mkdirof "$destl" if [ -f "$destl" ]; then if testdiff "$src" "$destl"; then cat "$src" >"$destl"; edot $? "REPL ${src#$osrcdir/} --> ${destl#$odestdir/}" fi else cp_a "$src" "$destl"; edot $? "NEW ${src#$osrcdir/} --> ${destl#$odestdir/}" fi continue fi # si on arrive ici, c'est qu'il y a maintenant un fichier # upstream pour un fichier local créé manuellement avec # local-create. Il faudra donc potentiellement intégrer des # modifications. fi # ici, le fichier upstream est potentiellement différent du fichier # orig déjà existant. il nous faut donc vérifier s'il y a eu # modification avant de copier cette nouvelle version. local -a versions; local destonv same version destov array_copy versions VERSIONS array_reverse versions destonv="$destdir/.--$destname--$newversion.$ORIGEXT" same= for version in "${versions[@]}"; do destov="$destdir/.--$destname--$version.$ORIGEXT" [ -f "$destov" ] || continue if testsame "$src" "$destov"; then same=1 break fi done [ -n "$same" ] && continue testsame "$src" "$desto" && continue # nouveau fichier différent. il faut le versionner mkdirof "$destonv" if [ -f "$destonv" ]; then if testdiff "$src" "$destonv"; then cat "$src" >"$destonv"; edot $? "REPL ${src#$osrcdir/} --> ${destonv#$odestdir/}" fi else cp_a "$src" "$destonv"; edot $? "NEW ${src#$osrcdir/} --> ${destonv#$odestdir/}" fi elif [ -d "$src" ]; then #################################################################### # copie d'un répertoire destname="$(__get_local "$srcname")" destl="$destdir/$destname" if [ ! -d "$destl" ]; then mkdir -p "$destl"; s=$? edot $s "DIR ${destl#$odestdir/}" [ $s == 0 ] || return 1 fi __unew_copy "$src" "$destl" "$newversion" "$osrcdir" "$odestdir" || return 1 else edotw 1 "$src: fichier ignoré" fi done return 0 } function upstream_new_help() { uecho "$scriptname upstream-new: intégrer une nouvelle distribution upstream USAGE $scriptname upstream-new [WORKDIR] Les nouveaux fichiers sont copiés tout de suite dans le répertoire de travail. Par contre, les modifications ne sont intégrées qu'avec la commande local-patch. Pour chacun des fichiers orig, si le fichier correspondant de la distribution upstream n'a pas été modifié, alors ce fichier n'est pas intégré. OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. -V, --version VERSION Spécifier la version de l'archive qui est intégrée. Normalement, cette information est calculée automatiquement à partir du nom de l'archive. Si la source est un répertoire ou une archive sans numéro de version, cette option est requise. -O, --origin ORIGIN Spécifier un répertoire origine qui contient soit la distribution non modifiée, soit une autre environnement udist pour la même distribution. Si la source est un répertoire et que l'origine n'est pas déjà spécifiée dans la configuration, cette option est automatiquement activée. --no-origin Ne pas mettre à jour la valeur de l'origine --auto-unwrap Si l'archive ne contient qu'un seul répertoire à la racine nommé d'après le nom de base de l'archive, c'est le contenu de ce répertoire qui est considéré. C'est l'option par défaut. Le test est effectué avec et sans la version. Par exemple, si l'archive est product-x.y.zip, et qu'elle contient un unique répertoire nommé 'product-x.y' ou 'product' alors intégrer le contenu de ce répertoire. -e, --unwrap Si l'archive ne contient qu'un seul répertoire à la racine, intégrer inconditionellement le contenu de se répertoire. --no-unwrap Intégrer tel quel le contenu de l'archive. --force Forcer l'intégration de la nouvelle version, même si elle a déjà été intégrée. -n Ne pas appeler '$scriptname local-patch' après l'intégration de la nouvelle version" } function upstream_new_cmd() { eval "$(udist_local)" local version= local origin= local noorigin= unwrap=auto force= nopatch= parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with upstream_new_help' \ "${UDISTOPTS[@]}" \ -V:,--version: version= \ -O:,--origin: origin= \ --no-origin noorigin=1 \ --auto-unwrap unwrap=auto \ --no-unwrap unwrap= \ -e,--unwrap unwrap=1 \ -k skiploneroot= \ --force force=1 \ -n nopatch=1 \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -d "$2" ] && workdir="$(find_workdir "$2")" __after_parse eval "$(__load_udist)" local srcdir archive archive="$1"; shift if [ -f "$archive" ]; then is_archive "$archive" || die "$archive: doit être un fichier archive" [ -n "$version" ] || version="$(get_archive_version "$archive")" elif [ -d "$archive" ]; then srcdir="$(abspath "$archive")" archive= if [ -z "$noorigin" -a -z "$ORIGIN" -a -z "$origin" ]; then # exprimer l'origine relativement à workdir origin="$(relpath "$srcdir" "$workdir")" fi else die "$archive: fichier introuvable" fi read_value "Entrez un identifiant pour cette version" version "$version" || die if [ -z "$force" ] && array_contains VERSIONS "$version"; then die "Vous avez déjà intégré la version $version" fi if [ -n "$archive" ]; then ac_set_tmpdir tmpd ebegin "Extraction de $(ppath "$archive")" extract_archive "$archive" "$tmpd" & ewait $! eend srcdir="$tmpd" if [ -n "$unwrap" ]; then local -a files array_lsall files "$srcdir" "*" ".*" if [ "${#files[*]}" -eq 1 ]; then local file="${files[0]}" if [ "$unwrap" == auto ]; then # nom de l'archive avec la version local banv="$(get_archive_basename "$archive")" # nom de l'archive sans la version local ban="${banv%$(get_archive_version "$archive")}" local filename="$(basename "$file")" [ "$filename" == "$banv" -o "$filename" == "$ban" ] || unwrap= fi [ -n "$unwrap" -a -d "$file" ] && srcdir="$file" fi fi fi ebegin "Copie des fichiers" __unew_copy "$srcdir" "$workdir" "$version" "$srcdir" "$workdir" eend estep "Maj de la configuration" array_addu VERSIONS "$version" __save_udist "" VERSION:version VERSIONS ${origin:+ORIGIN:origin} local_list_cmd -d "$workdir" --no-list [ -z "$nopatch" ] && local_patch_cmd -d "$workdir" ac_cleanall } ################################################################################ function upstream_clear_help() { uecho "$scriptname upstream-clear: USAGE $scriptname upstream-clear [options] [WORKDIR]" } function upstream_clear_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with upstream_clear_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -d "$1" ] && workdir="$(find_workdir "$1")" __after_parse ewarn "upstream-clear: non implémenté" } ################################################################################ function local_create_help() { uecho "$scriptname local-create: créer un fichier local USAGE $scriptname local-create [options] [WORKDIR] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant. -u, --update Mettre à jour la liste des fichiers locaux après l'ajout. C'est l'option par défaut. -n, --no-update Ne pas mettre à jour la liste des fichiers avec locaux après l'ajout. Cette option ne devrait pas être utilisée sauf dans des cas très spécifiques." } function local_create_cmd() { eval "$(udist_local)" local update=1 parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_create_help' \ "${UDISTOPTS[@]}" \ -u,--update update=1 \ -n,--no-update update= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$workdir" -a -d "$1" ]; then workdir="$(find_workdir "$1")" && shift [ -n "$workdir" ] && estepn "Sélection du répertoire de travail $(ppath "$workdir")" else [ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" [ -z "$workdir" -a ! -e "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" fi __after_parse [ -n "$*" ] || die "Vous devez spécifier les fichiers locaux à créer" if [ -n "$update" ]; then eval "$(__load_udist)" else local -a LOCALS fi local file relfile for file in "$@"; do if withinpath "$workdir" "$file"; then if [ ! -f "$file" ]; then ask_yesno "$file: fichier introuvable. Voulez-vous le créer?" O || continue touch "$file" || continue fi file="$(abspath "$file")" relfile="$(relpath "$file" "$workdir")" if [ -n "$(__list_origfiles "$file")" ]; then estep "$relfile: nop" else array_addu LOCALS "$relfile" ebegin "$relfile" cp "$file" "$(__get_orig "$file")" eend $? fi else eerror "$file: ne se trouve pas dans $workdir" fi done if [ -n "$update" ]; then estep "Maj de la configuration" __save_udist "" LOCALS fi } ################################################################################ function local_edit_help() { uecho "$scriptname local-edit: editer un fichier local USAGE $scriptname local-edit [options] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_edit_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_edit_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" __after_parse local_create_cmd -d "$workdir" -qy "$@" "$EDITOR" "$@" } ################################################################################ function local_copy_help() { uecho "$scriptname local-copy: copier un fichier USAGE $scriptname local-copy [options] SRCFILE DESTFILE OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier SRCFILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_copy_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_copy_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" __after_parse ewarn "local-copy: non implémenté" } ################################################################################ function local_move_help() { uecho "$scriptname local-move: déplacer un fichier USAGE $scriptname local-move [options] SRCFILE DESTFILE OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier SRCFILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_move_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_move_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" __after_parse ewarn "local-move: non implémenté" } ################################################################################ function local_remove_help() { uecho "$scriptname local-remove: supprimer un fichier USAGE $scriptname local-remove [options] FILE OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_remove_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_remove_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" __after_parse ewarn "local-remove: non implémenté" } ################################################################################ function local_tag_help() { uecho "$scriptname local-tag: gérer les fichiers de tag USAGE $scriptname local-tag [options] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_tag_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_tag_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -f "$1" ] && workdir="$(find_workdir "$(dirname "$1")")" __after_parse ewarn "local-tag: non implémenté" } ################################################################################ function local_switch_help() { uecho "$scriptname local_switch: changer le tag courant USAGE $scriptname local_switch [options] TOTAG [FILE] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant. --from FROMTAG Ne faire le changement que si le tag courant est FROMTAG. Si le tag est composite, les tags doivent être séparés par %, e.g. tag1%tag2" } function local_switch_cmd() { eval "$(udist_local)" local fromctag parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_switch_help' \ "${UDISTOPTS[@]}" \ --from: fromctag= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -d "$2" ] && workdir="$(find_workdir "$2")" [ -z "$workdir" -a -f "$2" ] && workdir="$(find_workdir "$(dirname "$2")")" __after_parse local toctag="$1"; shift [ -n "$toctag" ] || die "Vous devez spécifier le tag de destination" fromctag="$(__norm_ctag "$fromctag")" toctag="$(__norm_ctag "$toctag")" [ -n "$*" ] || set -- "$workdir" local -a localfiles tagfiles local localfile localdir doswitch tagfile ctag oldtagfile oldctag for localfile in "$@"; do etitle "$localfile" if ! withinpath "$workdir" "$localfile"; then eerror "$localfile: ne se trouve pas dans $workdir" continue fi if [ -d "$localfile" ]; then # cas particulier, c'est un répertoire, il faut lister tous les # fichiers locaux local basedir="$localfile" array_from_lines localfiles "$(__list_localfiles "$basedir")" for localfile in "${localfiles[@]}"; do localfile="$basedir/$localfile" localdir="$(dirname "$localfile")" doswitch=1 array_from_lines tagfiles "$(__list_tagfiles "$localfile")" oldtagfile="$(__get_curtagfile "$localfile")" oldctag=$(__get_ctag "$oldtagfile") if [ -z "$oldtagfile" ]; then doswitch= if [ -n "${tagfiles[*]}" ]; then eerror "$(ppath "$localfile"): Modifications locales sur le fichier. Veuillez utiliser local-tag pour corriger ce problème." fi elif [ "$oldctag" == "$toctag" ]; then # le fichier a déjà le bon tag doswitch= elif [ -z "${tagfiles[*]}" ]; then doswitch= elif [ -n "$fromctag" ]; then tagfile="$(__get_tagfile "$localfile" "$fromctag" tagfiles)" if [ -z "$tagfile" ]; then doswitch= elif ! testsame "$localfile" "$localdir/$tagfile"; then ctag="$(__get_ctag "$tagfile")" ewarn "$(ppath "$localfile"): Fichier ignoré (tag courant $oldctag, attendu $fromctag)" doswitch= fi fi if [ -n "$doswitch" ]; then tagfile="$(__get_tagfile "$localfile" "$toctag" tagfiles)" if [ -n "$tagfile" ]; then copy_update "$localdir/$tagfile" "$localfile" && estepn "$(ppath "$localfile"): $oldctag --> $toctag" fi fi done elif [ -f "$localfile" ]; then # c'est un fichier localdir="$(dirname "$localfile")" doswitch=1 array_from_lines tagfiles "$(__list_tagfiles "$localfile")" oldtagfile="$(__get_curtagfile "$localfile")" oldctag=$(__get_ctag "$oldtagfile") if [ -z "$oldtagfile" ]; then doswitch= if [ -n "${tagfiles[*]}" ]; then eerror "Modifications locales sur le fichier. Veuillez utiliser local-tag pour corriger ce problème." fi elif [ "$oldctag" == "$toctag" ]; then # le fichier a déjà le bon tag doswitch= elif [ -z "${tagfiles[*]}" ]; then ewarn "Fichier ignoré (pas de tags)" doswitch= elif [ -n "$fromctag" ]; then tagfile="$(__get_tagfile "$localfile" "$fromctag" tagfiles)" if [ -z "$tagfile" ]; then ewarn "Fichier ignoré (pas de tag $fromctag)" doswitch= elif ! testsame "$localfile" "$localdir/$tagfile"; then ctag="$(__get_ctag "$tagfile")" ewarn "Fichier ignoré (tag courant $oldctag, attendu $fromctag)" doswitch= fi fi if [ -n "$doswitch" ]; then tagfile="$(__get_tagfile "$localfile" "$toctag" tagfiles)" if [ -z "$tagfile" ]; then ewarn "Fichier ignoré (pas de tag $toctag)" else copy_update "$localdir/$tagfile" "$localfile" && estepn "$oldctag --> $toctag" fi fi else eerror "$localfile: fichier introuvable" fi eend done } ################################################################################ function __lput_copyto() { local destdir="$1" for localfile in "${localfiles[@]}"; do copy_update "$workdir/$localfile" "$destdir/$localfile" && edot 0 "$(ppath "$destdir/$localfile")" done } function local_put_help() { uecho "$scriptname local-put: copier les fichiers locaux dans un répertoire distant USAGE $scriptname local-put [options] [WORKDIR] <[user@host:]destdir> OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. -u, --update Mettre à jour d'abord la liste des fichiers locaux avec local-list. -n, --no-update Ne pas mettre à jour la liste des fichiers avec local-list. Utiliser simplement le cache. C'est l'option par défaut --copy-origs Copier les fichiers orig en plus des fichiers locaux --copy-tags Copier les fichiers de tag en plus des fichiers locaux -a, --all Copier le fichier .udist et les fichiers orig et de tag en plus des fichiers locaux -S, --ssh SSH Spécifier la commande ssh à utiliser pour la copie avec rsync. -R, --rsync RSYNC Spécifier la commande rsync à utiliser pour la copie. -O, --owner OWNER Spécifier le propriétaire des fichiers à l'arrivée. La modification se fait en se connectant avec ssh." } function local_put_cmd() { eval "$(udist_local)" local update= copyorigs= copytags= copyall= local ssh= rsync= owner= parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_put_help' \ "${UDISTOPTS[@]}" \ -u,--update update=1 \ -n,--no-update update= \ --copy-origs copyorigs=1 \ --copy-tags copytags=1 \ -a,--all,--copy-all copyall=1 \ -S:,--ssh: ssh= \ -R:,--rsync: rsync= \ -O:,--owner: owner= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$workdir" -a $# -ge 2 -a -d "$1" ]; then workdir="$(find_workdir "$1")" && shift [ -n "$workdir" ] && estepn "Sélection du répertoire de travail $(ppath "$workdir")" fi __after_parse local remote="$1" if [ -z "$remote" ]; then # Si la destination n'est pas spécifiée, prendre la valeur de ORIGIN eval "$(__load_udist)" remote="$ORIGIN" [ -n "$remote" ] && enote "Sélection automatique de la destination $remote" fi [ -n "$remote" ] || die "Vous devez spécifier la destination" local userhost destdir if [[ "$remote" == *:* ]]; then # remote est de la forme userhost:destdir splitfsep "$remote" : userhost destdir else # remote est de la forme destdir userhost= destdir="$remote" [ -d "$destdir" ] || die "$destdir: répertoire introuvable" fi [ -n "$update" ] && local_list_cmd -d "$workdir" --no-list eval "$(__load_udist)" local -a localfiles; array_copy localfiles LOCALS if [ -n "$copyorigs" -o -n "$copytags" -o -n "$copyall" ]; then local -a origlocalfiles local local localdir origfile tagfile array_copy origlocalfiles localfiles localfiles=() [ -n "$copyall" ] && array_add localfiles .udist for localfile in "${origlocalfiles[@]}"; do array_add localfiles "$localfile" localdir="$(dirname "$localfile")" if [ -n "$copyorigs" -o -n "$copyall" ]; then array_from_lines origfiles "$(__list_origfiles "$workdir/$localfile")" for origfile in "${origfiles[@]}"; do array_add localfiles "$localdir/$origfile" done fi if [ -n "$copytags" -o -n "$copyall" ]; then array_from_lines tagfiles "$(__list_tagfiles "$workdir/$localfile")" for tagfile in "${tagfiles[@]}"; do array_add localfiles "$localdir/$tagfile" done fi done fi if [ -n "$userhost" ]; then # copie distante ac_set_tmpdir tmpdir ebegin "Préparation de la copie" __lput_copyto "$tmpdir" eend estep "Copie distante vers $userhost:$destdir" local -a cmd cmd=("${rsync:-rsync}") [ -n "$ssh" ] && cmd=("${cmd[@]}" -e "$ssh") "${cmd[@]}" -rv "$tmpdir/" "$userhost:$destdir" if [ -n "$owner" ]; then estep "Modification du propriétaire à $owner" local script= for localfile in "${localfiles[@]}"; do [ -n "$script" ] && script="$script; " script="$script$(qvals chown "$owner" "$destdir/$localfile")" done "${ssh:-ssh}" -qt "$userhost:$destdir" "$script" fi else # copie locale withinpath "$workdir" "$destdir" && die "Impossible de copier dans $(ppath "$destdir")" ebegin "Copie des fichiers" __lput_copyto "$destdir" eend if [ -n "$owner" ]; then ebegin "Modification du propriétaire à $owner" for localfile in "${localfiles[@]}"; do chown "$owner" "$destdir/$localfile"; edot $? "$(ppath "$destdir/$localfile")" done eend fi fi } ################################################################################ function local_get_help() { uecho "$scriptname local-get: intégrer des fichiers d'un répertoire distant et en faire des fichiers locaux USAGE $scriptname local-get [options] <[user@host:]destdir> [WORKDIR] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. -l Faire des liens physiques au lieu de simplement copier les fichiers -s Faire des liens symboliques au lieu de liens physiques -S, --ssh SSH Spécifier la commande ssh à utiliser pour la copie avec rsync. -R, --rsync RSYNC Spécifier la commande rsync à utiliser pour la copie." } function local_get_cmd() { eval "$(udist_local)" local link= symbolic= local ssh= rsync= parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_get_help' \ "${UDISTOPTS[@]}" \ -l,--link link=1 \ -s,--symbolic '$link=1; symbolic=1' \ -S:,--ssh: ssh= \ -R:,--rsync: rsync= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -d "$2" ] && workdir="$(find_workdir "$2")" __after_parse local remote="$1" if [ -z "$remote" ]; then # Si la destination n'est pas spécifiée, prendre la valeur de ORIGIN eval "$(__load_udist)" remote="$ORIGIN" [ -n "$remote" ] && enote "Sélection automatique de la source $remote" fi [ -n "$remote" ] || die "Vous devez spécifier la source" local userhost srcdir if [[ "$remote" == *:* ]]; then # remote est de la forme userhost:srcdir splitfsep "$remote" : userhost srcdir else # remote est de la forme srcdir userhost= srcdir="$remote" [ -d "$srcdir" ] || die "$srcdir: répertoire introuvable" withinpath "$workdir" "$srcdir" && die "Impossible de copier depuis $(ppath "$srcdir")" fi if [ -n "$userhost" ]; then if [ -n "$link" ]; then ewarn "Impossible de faire des liens pour des fichiers distants" link= fi # copie distante etitle "Copie distante depuis $userhost:$srcdir" ac_set_tmpdir tmpdir local -a cmd cmd=("${rsync:-rsync}") [ -n "$ssh" ] && cmd=("${cmd[@]}" -e "$ssh") "${cmd[@]}" -rv "$userhost:$srcdir/" "$tmpdir" eend srcdir="$tmpdir" fi etitle "Intégration des fichiers" array_from_lines srcs "$(cd "$srcdir"; find -type f | filter_vcspath | sed 's/^.\///')" for src in "${srcs[@]}"; do mkdirof "$workdir/$src" || die local_create_cmd -d "$workdir" -qy "$src" if [ -n "$link" ]; then [ -e "$workdir/$src" ] && rm "$workdir/$src" ln ${symbolic:+-s} "$srcdir/$src" "$workdir/$src" else [ -L "$workdir/$src" ] && rm "$workdir/$src" copy_update "$srcdir/$src" "$workdir/$src" && estep "$(ppath "$workdir/$src")" fi done eend } ################################################################################ function local_list_help() { uecho "$scriptname local-list: lister les fichiers locaux USAGE $scriptname local-list [options] [WORKDIR] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. -n, --no-update Ne pas mettre à jour la liste des fichiers. Utiliser simplement le cache. Implique l'option --no-cache --no-list Ne pas lister les fichiers. Faire simplement la mise à jour du cache. --no-cache Ne pas mettre à jour le cache des fichiers locaux. Normalement, toutes les autres commandes utilisent les informations du cache." } function local_list_cmd() { eval "$(udist_local)" local update=1 local list=1 local cache=1 parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_list_help' \ "${UDISTOPTS[@]}" \ -u,--update update=1 \ -n,--no-update '$update=; cache=' \ -l,--list list=1 \ --no-list list= \ -c,--cache cache=1 \ --no-cache cache= \ @ args -- "$@" && set -- "${args[@]}" || die "$args" [ -z "$workdir" -a -d "$1" ] && workdir="$(find_workdir "$1")" __after_parse eval "$(__load_udist)" local -a localfiles tags tagfiles localtags local tagfile localtag if [ -n "$update" ]; then array_from_lines localfiles "$(__list_localfiles "$workdir")" for localfile in "${localfiles[@]}"; do array_from_lines tagfiles "$(__list_tagfiles "$workdir/$localfile")" for tagfile in "${tagfiles[@]}"; do __init_tags localtags "$tagfile" array_extendu tags localtags done done array_from_lines tags "$(array_to_lines tags | csort -u)" else array_copy localfiles LOCALS array_copy tags TAGS fi if [ -n "$cache" ]; then __save_udist "" LOCALS:localfiles TAGS:tags fi if [ -n "$list" ]; then [ -n "$ORIGIN" ] && echo "# origin: $(relpath "$ORIGIN" "" "$workdir")" echo "# version: $VERSION" local -a versions tagfiles; local localdir for localfile in "${localfiles[@]}"; do localfile="$workdir/$localfile" localdir="$(dirname "$localfile")" line="$(relpath "$localfile")" if [ ! -f "$localfile" ]; then line="$line ${COULEUR_ROUGE}!${COULEUR_NORMALE}" fi array_from_lines versions "$(__list_origfiles "$localfile")" array_map versions __get_version array_del versions "$version" if [ -n "${versions[*]}" ]; then line="$line ${COULEUR_JAUNE}pending${COULEUR_NORMALE}($(array_join versions ", "))" fi array_from_lines tagfiles "$(__list_tagfiles "$localfile")" if [ -n "${tagfiles[*]}" ]; then local tmpline= first=1 foundcur= for tagfile in "${tagfiles[@]}"; do if [ -n "$first" ]; then first=; else tmpline="$tmpline, "; fi if testsame "$localfile" "$localdir/$tagfile"; then tmpline="$tmpline${COULEUR_BLEUE}$(__get_ctag "$tagfile")${COULEUR_NORMALE}" foundcur=1 else tmpline="$tmpline$(__get_ctag "$tagfile")" fi done if [ -n "$foundcur" ]; then line="$line tags($tmpline)" else line="$line ${COULEUR_ROUGE}tags${COULEUR_NORMALE}($tmpline)" fi fi echo "$line" done fi } ################################################################################ function upstream_diff_help() { uecho "$scriptname upstream-diff: USAGE $scriptname upstream-diff [options] WORKDIR $scriptname upstream-diff [options] [FILEs...] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function upstream_diff_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with upstream_diff_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$workdir" -a -d "$1" ]; then workdir="$(find_workdir "$1")" && shift elif [ -z "$workdir" -a -f "$1" ]; then workdir="$(find_workdir "$(dirname "$1")")" fi __after_parse ewarn "upstream-diff: non implémenté" } ################################################################################ function local_diff_help() { uecho "$scriptname local-diff: USAGE $scriptname local-diff [options] WORKDIR $scriptname local-diff [options] [FILEs...] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_diff_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_diff_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$workdir" -a -d "$1" ]; then workdir="$(find_workdir "$1")" && shift elif [ -z "$workdir" -a -f "$1" ]; then workdir="$(find_workdir "$(dirname "$1")")" fi __after_parse ewarn "local-diff: non implémenté" } ################################################################################ function local_patch_help() { uecho "$scriptname local-patch: USAGE $scriptname local-patch [options] WORKDIR $scriptname local-patch [options] [FILEs...] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_patch_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_patch_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$workdir" -a -d "$1" ]; then workdir="$(find_workdir "$1")" && shift elif [ -z "$workdir" -a -f "$1" ]; then workdir="$(find_workdir "$(dirname "$1")")" fi __after_parse ewarn "local-patch: non implémenté" } ################################################################################ function local_forget_help() { uecho "$scriptname local-forget: USAGE $scriptname local-forget [options] WORKDIR $scriptname local-forget [options] [FILEs...] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. Si cette option n'est pas spécifiée et que le fichier FILE existe, le calcul est effectué à partir de son répertoire au lieu du répertoire courant." } function local_forget_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with local_forget_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -z "$workdir" -a -d "$1" ]; then workdir="$(find_workdir "$1")" && shift elif [ -z "$workdir" -a -f "$1" ]; then workdir="$(find_workdir "$(dirname "$1")")" fi __after_parse ewarn "local-forget: non implémenté" } ################################################################################ # XXX à migrer puis supprimer function diff_help() { uecho "$scriptname diff: afficher les différences entre les versions USAGE $scriptname diff [options] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant. -o Afficher les différences entre la version originale actuelle et la version précédente (par défaut). Ces différences peuvent être intégrées dans le répertoire de travail avec la commande '$scriptname patch' -c Afficher les différences entre la copie de travail et la version originale." } function diff_cmd() { eval "$(udist_local)" local mode=orig parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with diff_help' \ "${UDISTOPTS[@]}" \ -o,--orig mode=orig \ -c,--work mode=work \ @ args -- "$@" && set -- "${args[@]}" || die "$args" __after_parse local cwd="$(pwd)" cd "$workdir" if [ "$mode" == "orig" ]; then if [ -d ".__prev" -a -d ".__orig" ]; then cdiff -urN .__prev .__orig | page_maybe else einfo "Pas de version précédente à comparer" fi elif [ "$mode" == "work" ]; then if [ -d ".__orig" ]; then cdiff -urN -x .svn -x .git -x .__prev -x .__orig -x .udist .__orig . | page_maybe else einfo "Pas de version originale à comparer" fi fi cd "$cwd" } ################################################################################ # XXX à migrer puis supprimer function patch_help() { uecho "$scriptname patch: intégrer les modifications dans le répertoire de travail USAGE $scriptname patch [options] OPTIONS -d WORKDIR Spécifier le répertoire de travail au lieu du répertoire courant." } function patch_cmd() { eval "$(udist_local)" parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with patch_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" __after_parse local patch ac_set_tmpfile patch diff_cmd -qo >"$patch" if [ -s "$patch" ]; then page_maybe <"$patch" ask_yesno "Voulez-vous appliquer ces modifications à la copie de travail?" X || die local cwd="$(pwd)" cd "$workdir" patch -p1 <"$patch" || die rm -rf ".__prev" || die cd "$cwd" else einfo "Pas de modifications à intégrer" fi } ################################################################################ workdir= parse_opts + "${PRETTYOPTS[@]}" \ --help '$exit_with display_help' \ "${UDISTOPTS[@]}" \ @ args -- "$@" && set -- "${args[@]}" || die "$args" __after_parse initial # Traduire la commande [ -n "$*" ] || set -- "$DEFAULT_CMD" cmd= found_cmd= while [ -z "$found_cmd" ]; do cmd="$1"; shift; found_cmd=1 [ -n "$cmd" ] || break for cmd_alias in "${CMD_ALIASES[@]}"; do splitpair "$cmd_alias" src dest if [ "$cmd" == "$src" ]; then eval "set -- $dest \"\$@\"" found_cmd= break fi done done case "$cmd" in "") exit_with display_help;; init) init_cmd "$@";; upstream-new) upstream_new_cmd "$@";; upstream-clear) upstream_clear_cmd "$@";; local-create) local_create_cmd "$@";; local-edit) local_edit_cmd "$@";; local-copy) local_copy_cmd "$@";; local-move) local_move_cmd "$@";; local-remove) local_remove_cmd "$@";; local-tag) local_tag_cmd "$@";; local-switch) local_switch_cmd "$@";; local-put) local_put_cmd "$@";; local-get) local_get_cmd "$@";; local-list) local_list_cmd "$@";; upstream-diff) upstream_diff_cmd "$@";; local-diff) local_diff_cmd "$@";; local-patch) local_patch_cmd "$@";; local-forget) local_forget_cmd "$@";; *) die "$cmd: commande incorrecte";; esac