Intégration de la branche update-pff

This commit is contained in:
Jephté Clain 2018-03-06 13:08:59 +04:00
commit e20757b45e
1 changed files with 329 additions and 53 deletions

382
pff
View File

@ -2,9 +2,12 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
SCRIPT_ALIASES=(
pf0:-0
pfn:-N
pfg:-g
pfb:-b
pfs:-s
pfa:-a
pfb:-b
pfe:-e
pfd:-d
)
@ -55,16 +58,45 @@ function __pff_profiles() {
pffdir="$(dirname -- "$pffdir")"
done
}
function __pfe_profiles() {
echo ALL
__pff_profiles "$@" | grep -vxF Base
}
function __pfs_completion() {
local cur
_get_comp_words_by_ref cur
COMPREPLY=($(compgen -W "$(__pff_profiles)" "$cur"))
}
complete -F __pfs_completion -o bashdefault -o default pfs
function __pfe_completion() {
local cur prev opt comp
_get_comp_words_by_ref cur prev
if [[ "$prev" == -*p ]]; then
COMPREPLY=($(compgen -W "$(__pfe_profiles)" -- "$cur"))
elif [ "$prev" == --profile ]; then
COMPREPLY=($(compgen -W "$(__pfe_profiles)" -- "$cur"))
elif [[ "$cur" == -*p* ]]; then
comp="${cur#-*p}"; opt="${cur:0:$((${#cur}-${#comp}))}"
COMPREPLY=($(compgen -W "$(__pfe_profiles "$opt")" -- "$cur"))
fi
}
complete -F __pfe_completion -o bashdefault -o default pfe
function __pff_completion() {
local cur prev opt comp
_get_comp_words_by_ref cur prev
if [[ "$prev" == -*s ]]; then
if [ "${COMP_WORDS[1]}" == -e -o "${COMP_WORDS[1]}" == --edit ]; then
# ne compléter -p que si on est en mode --edit
if [[ "$prev" == -*p ]]; then
COMPREPLY=($(compgen -W "$(__pfe_profiles)" -- "$cur"))
elif [ "$prev" == --profile ]; then
COMPREPLY=($(compgen -W "$(__pfe_profiles)" -- "$cur"))
elif [[ "$cur" == -*p* ]]; then
comp="${cur#-*p}"; opt="${cur:0:$((${#cur}-${#comp}))}"
COMPREPLY=($(compgen -W "$(__pfe_profiles "$opt")" -- "$cur"))
fi
elif [[ "$prev" == -*s ]]; then
COMPREPLY=($(compgen -W "$(__pff_profiles)" -- "$cur"))
elif [ "$prev" == --switch ]; then
COMPREPLY=($(compgen -W "$(__pff_profiles)" -- "$cur"))
elif [[ "$cur" == -*s* ]]; then
comp="${cur#-*s}"; opt="${cur:0:$((${#cur}-${#comp}))}"
@ -77,7 +109,7 @@ complete -F __pff_completion -o bashdefault -o default pff
fi
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS multiconf
urequire DEFAULTS multiconf vcs
function display_help() {
uecho "$scriptname: gestion de modifications locales
@ -148,11 +180,11 @@ supportées sont:
Intégrer une distribution complète. Par défaut, les archives avec
l'extension .war sont considérées commes des livraisons complètes. Si
la source est un répertoire ou une archive sans extension, l'une des
options -F ou -P est requise.
-P, --patch-archive
options -F ou -H est requise.
-H, --patch-archive
Intégrer un patch. Par défaut, les archives avec l'extension .zip sont
considérées comme des patches. Si la source est un répertoire ou une
archive sans extension, l'une des options -F ou -P est requise.
archive sans extension, l'une des options -F ou -H est requise.
Avec une distribution de type patch, on considère que les fichiers
livrés ne sont pas des fichiers origines. Il n'y a donc aucun traitement
particulier: l'archive est simplement intégrée telle quelle.
@ -169,11 +201,18 @@ supportées sont:
--no-unwrap
Intégrer tel quel le contenu de l'archive.
-p, --patch [WORKDIR]
-g, --patch [WORKDIR]
Intégrer les modifications entrantes sur les fichiers nouvellement
arrivés via l'option --new
--ask-commit
-c, --commit
--no-commit
Après l'intégration avec succès d'un patch, demander à l'utilisateur
s'il veut faire commit & push dans git (--ask-commit, la valeur par
défaut), le faire sans confirmation (--commit), ou ne jamais le faire
(--no-commit)
-a, --add-global FILES...
-b, --add-global FILES...
Ajouter/Identifier un fichier comme un fichier local pour tous les
profils. Le fichier est copié dans le profil Base.
@ -186,17 +225,35 @@ supportées sont:
-s, --switch PROFILE [WORKDIR]
Basculer le profil courant
-b, --add-local FILES...
-a, --add-local FILES...
Ajouter/Identifier un fichier comme un fichier local et le rendre
spécifique au profil courant.
-e, --edit FILES...
Editer des fichiers, implique --add-local
-p, --profile PROFILE
Pour l'option --edit, sélectionner le profil spécifié comme celui
concerné pour les fichier mentionnés après cette option. Par exemple:
$scriptname -e A -pprod B C -ptest D
Edite le fichier A du profil courant, les fichiers B et C du profil prod
et le fichier D du profil test.
Le profil ALL est spécial et permet d'éditer le fichier dans tous les
profils *où il existe*, excepté Base parce que ce profil contient des
fichiers qui ne devraient pas être modifiés.
Pour tous les autres profils, si le fichier n'existe pas dans le profil
spécifié il est rajouté dans le profil avant son édition.
Attention: pour que l'option -p/--profile soit correctement reconnue
avec l'option -e/--edit, il faut que cette dernière option soit
mentionnée en premier sur la ligne de commande.
-P, --prod
-T, --test
-A, --all-profiles
Raccourcis pour respectivement -pprod, -ptest et -pALL
-d, --diff [DESTP [WORKDIR]]
-d, --diff [SRCP DESTP [WORKDIR]]
Afficher la différence entre entre deux profils. Avec la première
syntaxe, comparer le profil courant au profil DESTP. Avec la deuxième
syntaxe, comparer le profil SRCP au DESTP.
syntaxe, comparer le profil DESTP au profil courant. Avec la deuxième
syntaxe, comparer le profil DESTP au profil SRCP.
-l, --list-names
N'afficher que les noms des fichiers qui sont différents
@ -273,9 +330,15 @@ function get_profiles() {
list_dirs "$pffdir/pff") | sort -u | grep -vxF Current
}
function get_user_profiles() {
# afficher tous les profils modifiables du projet pff $1 (c'est à dire tous
# les profils valides excepté Base)
get_profiles "$@" | grep -vxF Base
}
function get_first_profile() {
# afficher le premier profil autre que Base du projet pff $1
get_profiles "$@" | grep -vxF Base | head -n1
get_user_profiles "$@" | head -n1
}
function get_local_files() {
@ -338,22 +401,36 @@ function get_bfile() { get_pfile "$1" Base "$2"; }
function get_Cfile() { get_pfile "$1" Common "$2"; }
function get_cfile() { get_pfile "$1" Current "$2"; }
function get_vlfiles() {
function get_vlfiles_nostrip() {
# afficher tous les fichiers de version
local pffdir="$1" rfile="$2" profile="${3:-Base}"
local pffdir="$1" rfile="$2" profile="${3:-Base}" version="$4"
[ -d "$pffdir/pff/$profile" ] || return
if [ -n "$rfile" ]; then
find "$pffdir/pff/$profile" \
-type f -path "$pffdir/pff/$profile/${rfile}__pv-*__" -o \
-type l -path "$pffdir/pff/$profile/${rfile}__pv-*__" \
| sed "s|^$pffdir/pff/$profile/||"
if [ -n "$version" ]; then
if [ -n "$rfile" ]; then
find "$pffdir/pff/$profile" \
-type f -path "$pffdir/pff/$profile/${rfile}__pv-${version}__" -o \
-type l -path "$pffdir/pff/$profile/${rfile}__pv-${version}__"
else
find "$pffdir/pff/$profile" \
-type f -name "*__pv-${version}__" -o \
-type l -name "*__pv-${version}__"
fi
else
find "$pffdir/pff/$profile" \
-type f -name "*__pv-*__" -o \
-type l -name "*__pv-*__" \
| sed "s|^$pffdir/pff/$profile/||"
if [ -n "$rfile" ]; then
find "$pffdir/pff/$profile" \
-type f -path "$pffdir/pff/$profile/${rfile}__pv-*__" -o \
-type l -path "$pffdir/pff/$profile/${rfile}__pv-*__"
else
find "$pffdir/pff/$profile" \
-type f -name "*__pv-*__" -o \
-type l -name "*__pv-*__"
fi
fi
}
function get_vlfiles() {
local pffdir="$1" rfile="$2" profile="${3:-Base}" version="$4"
get_vlfiles_nostrip "$@" | sed "s|^$pffdir/pff/$profile/||"
}
function sync_vlfiles() {
# synchroniser les fichiers de version $3..@ dans tous les répertoires de
@ -365,7 +442,7 @@ function sync_vlfiles() {
if [ -n "$profile" ]; then
profiles=("$profile")
else
array_from_lines profiles "$(get_profiles "$pffdir" | grep -vxF Base)"
array_from_lines profiles "$(get_user_profiles "$pffdir")"
fi
local vlfile rfile prefix pfile plink tmp
for vlfile in "$@"; do
@ -520,7 +597,7 @@ function new__prepare_archive() {
disttype=patch
;;
*)
die "L'extension de l'archive n'est pas reconnue. Vous devez spécifier l'une des options --full-archive ou --patch-archive"
die "L'extension de l'archive n'est pas reconnue. Vous devez spécifier l'une des options -F ou -H"
;;
esac
fi
@ -548,7 +625,7 @@ function new__prepare_archive() {
fi
elif [ -d "$srcdir" ]; then
if [ "$disttype" == auto ]; then
die "La source est un répertoire. Vous devez spécifier l'une des option --full-archive ou --patch-archive"
die "La source est un répertoire. Vous devez spécifier l'une des option -F ou -H"
fi
ac_set_tmpdir tmpd
@ -562,7 +639,7 @@ function new__prepare_archive() {
}
function new_cmd() {
local autopatch="$1" version="$2" disttype="$3" unwrap="$4"; shift; shift; shift; shift
local autopatch="$1" version="$2" disttype="$3" unwrap="$4" commit_policy="$5"; shift; shift; shift; shift; shift
local archive="$1" pffdir="$2"
ensure_pffdir pffdir "$pffdir"
@ -796,7 +873,8 @@ function new_cmd() {
if [ -n "$autopatch" ]; then
# lancer la commande patch pour intégrer les modifications
patch_cmd "$pffdir"
ask_yesno "Voulez-vous passer à l'intégration de cette version?" O &&
patch_cmd "$commit_policy" "$pffdir"
fi
}
@ -804,9 +882,167 @@ function new_cmd() {
# pff --patch
function patch_cmd() {
local pffdir="$1"
local commit_policy="$1" pffdir="$2"
local gitproject was_patched eop_version
local version profile rcfile curdir workdir controldir
local -a profiles vlfiles tmpfiles
ensure_pffdir pffdir "$pffdir"
# est-ce un projet suivi dans git?
(cd "$pffdir"; git_check_gitvcs) && gitproject=1 || gitproject=
array_from_lines profiles "$(get_user_profiles "$pffdir")"
if array_contains profiles Common; then
# toujours traiter Common en dernier
array_del profiles Common
array_add profiles Common
fi
while true; do
# si pas de version en cours, il n'y a rien à patcher
[ ${#PVERSIONS[*]} -gt 0 ] || break
eop_version=
for version in "${PVERSIONS[@]}"; do
have_profile_vlfiles=
have_base_vlfiles=
for profile in "${profiles[@]}"; do
array_from_lines vlfiles "$(get_vlfiles_nostrip "$pffdir" "" "$profile" "$version")"
if [ ${#vlfiles[*]} -gt 0 ]; then
have_profile_vlfiles=1
break
fi
done
[ -n "$have_profile_vlfiles" ] && break
array_from_lines vlfiles "$(get_vlfiles_nostrip "$pffdir" "" Base "$version")"
have_base_vlfiles=1
break
done
if [ -n "$have_profile_vlfiles" ]; then
# il faut patcher les fichiers du profil
etitle "Intégration de la version $version dans le profil $profile"
[ -n "$rcfile" ] || ac_set_tmpfile rcfile
[ -n "$workdir" ] && ac_clean "$workdir"
ac_set_tmpdir workdir
[ -n "$controldir" ] && ac_clean "$controldir"
ac_set_tmpdir controldir
curdir="$(pwd)"
cd "$workdir"
git init -q .
git checkout -q --orphan upstream
# rajouter les fichiers de Base dans la branche upstream
for vlfile in "${vlfiles[@]}"; do
setx bfile=get_bfile "${vlfile%__pv-${version}__}" "$pffdir"
setx rfile=get_rfile "$bfile" "$pffdir"
mkdirof "$rfile"
cp -a "$bfile" "$rfile"
done
git add -A
git commit -qm "Base"
# créer la branche v$version depuis upstream
git checkout -qb "v$version"
# rajouter les fichiers de Common s'ils existent (sauf si la branche c'est Common ^^)
if [ "$profile" != Common ]; then
for vlfile in "${vlfiles[@]}"; do
setx Cfile=get_Cfile "${vlfile%__pv-${version}__}" "$pffdir"
if [ -e "$Cfile" -o -L "$Cfile" ]; then
setx rfile=get_rfile "$Cfile" "$pffdir"
mkdirof "$rfile"
cp -a "$Cfile" "$rfile"
fi
done
git add -A
git commit -qm "Common"
fi
# rajouter les fichiers du profil
for vlfile in "${vlfiles[@]}"; do
setx pfile=get_pfile "${vlfile%__pv-${version}__}" "$profile" "$pffdir"
setx rfile=get_rfile "$pfile" "$pffdir"
mkdirof "$rfile"
cp -a "$pfile" "$rfile"
done
git add -A
git commit -qm "$profile"
# rebasculer vers upstream et rajouter les fichiers de patch
git checkout -q upstream
for vlfile in "${vlfiles[@]}"; do
setx rfile=get_rfile "${vlfile%__pv-${version}__}" "$pffdir"
mkdirof "$rfile"
cp -L "$vlfile" "$rfile"
done
git add -A
git commit -qm "$version"
# basculer vers la branche de version et tenter de merger upstream dans version
git checkout -q "v$version"
if git merge --no-commit upstream; then
# tout s'est bien passé
git commit -qm "v$version --> $profile"
else
# il y a eu une erreur. laisser l'utilisateur décider quoi faire
echo >"$rcfile" "#
[ -f /etc/bash.bashrc ] && . /etc/bash.bashrc
[ -f ~/.bashrc ] && . ~/.bashrc
$(qvals source "$ULIBDIR/ulib")
urequire DEFAULTS
function abort() { $(qvals touch "$controldir/ABORT"); exit; }
$(qvals cd "$workdir")
$(qvals eerror "Une erreur s'est produite: examinez la situation et faites les corrections nécessaires")
$(qvals eimportant "Puis tapez exit pour valider l'intégration de la version")
$(qvals eimportant "Sinon, tapez abort pour arrêter l'intégration de cette version")
"
"${SHELL:-bash}" --rcfile "$rcfile"
fi
[ -f "$controldir/ABORT" ] && break
# récupérer les versions modifiées et supprimer les fichiers de patch
for vlfile in "${vlfiles[@]}"; do
setx pfile=get_pfile "${vlfile%__pv-${version}__}" "$profile" "$pffdir"
setx rfile=get_rfile "$pfile" "$pffdir"
cp -a "$rfile" "$pfile"
rm "$vlfile"
done
cd "$curdir"
eend
elif [ -n "$have_base_vlfiles" ]; then
# il faut intégrer la nouvelle version dans Base
etitle "Finaliser intégration de la version $version"
for vlfile in "${vlfiles[@]}"; do
bfile="${vlfile%__pv-${version}__}"
mv "$vlfile" "$bfile"
done
eop_version=1
VERSION="$version"
array_del PVERSIONS "$VERSION"
conf_update "$pffdir/$PFFCONF" VERSION PVERSIONS
eend
fi
if [ -n "$gitproject" ]; then
local commit default
if [ -n "$eop_version" ]; then
msg="Intégration de la version $version"
else
msg="Correction du profil $profile pour la version $version"
fi
commit="$commit_policy"
if [ "$commit" == ask ]; then
if [ -n "$eop_version" ]; then
enote "Vous avez terminé l'intégration des patches de la version $version"
default=O
else
einfo "Vous avez intégré les patches de la version $version pour le profil $profile"
default=N
fi
ask_yesno "Voulez-vous enregistrer les modifications dans git?" $default || commit=
fi
if [ -n "$commit" ]; then
git add -A && git commit -qm "$msg" || return
if [ -z "$UTOOLS_VCS_OFFLINE" ]; then
git push -q
fi
fi
fi
done
}
#===========================================================
@ -980,16 +1216,27 @@ function add_local_cmd() {
# pff --edit
function edit_cmd() {
local pffdir file rfile pfile Pfile
local profile r
local -a edits
local profile="$1"; shift
local pffdir file rfile pfile Pfile r
local -a profiles edits args
ensure_pffdir pffdir
setx profile=get_current_profile "$pffdir"
enote "Edition des fichiers dans le profil $profile"
array_from_lines profiles "$(get_user_profiles "$pffdir")"
[ -n "$profile" ] || setx profile=get_current_profile "$pffdir"
enote "Dans le profil $profile:"
r=0
for file in "$@"; do
while [ $# -gt 0 ]; do
if [[ "$1" == -* ]]; then
# nouvelle option
local prev_profile="$profile"
args=(+ -p:,--profile: profile=)
parse_args "$@"; set -- "${args[@]}"
[ "$profile" != "$prev_profile" ] && enote "Dans le profil $profile:"
continue
fi
file="$1"; shift
if [ -d "$file" ]; then
ewarn "$file: est un répertoire. argument ignoré"
continue
@ -1000,16 +1247,31 @@ function edit_cmd() {
r=1
continue
}
add_local__link "$pfile" "$profile" "$pffdir" || {
ewarn "$file: erreur lors de la création du lien local"
r=1
continue
}
setx Pfile=get_pfile "$pfile" "$profile" "$pffdir"
array_add edits "$Pfile"
if [ "$profile" == ALL ]; then
local tmpp
for tmpp in "${profiles[@]}"; do
setx Pfile=get_pfile "$pfile" "$tmpp" "$pffdir"
[ -e "$Pfile" ] || continue
estep "Edition de $(ppath "$Pfile")"
array_add edits "$Pfile"
done
else
add_local__link "$pfile" "$profile" "$pffdir" || {
ewarn "$file: erreur lors de la création du lien local"
r=1
continue
}
setx Pfile=get_pfile "$pfile" "$profile" "$pffdir"
estep "Edition de $(ppath "$Pfile")"
array_add edits "$Pfile"
fi
done
"${EDITOR:-vi}" "${edits[@]}" || r=$?
if [ ${#edits[*]} -gt 0 ]; then
"${EDITOR:-vi}" "${edits[@]}" || r=$?
else
r=2
fi
return $r
}
@ -1087,11 +1349,11 @@ function diff_cmd() {
fi
fi
if [ -n "$list_names" ]; then
diff -q "$srcfile" "$destfile" >&/dev/null || echo "$srcfile"
diff -q "$destfile" "$srcfile" >&/dev/null || echo "$srcfile"
else
[ -n "$desc" ] && echo "$desc"
desc=
diff -ur "$srcfile" "$destfile"
diff -ur "$destfile" "$srcfile"
fi
done | page_maybe
}
@ -1160,6 +1422,11 @@ done
QUIET=1 # masquer les messages de git et rsync?
VERYQUIET=1 # masquer les messages de git commit?
parse_mode=
if [ "$1" == -e -o "$1" == --edit ]; then
parse_mode=+
fi
action=infos
autopatch=1
version=
@ -1167,8 +1434,10 @@ disttype=auto
ORIGEXTS=("${DEFAULT_ORIGEXTS[@]}")
PROTECTS=("${DEFAULT_PROTECTS[@]}")
unwrap=auto
commit_policy=ask
profile=
alternate=
args=(
args=($parse_mode
--help '$exit_with display_help'
-0,--init action=init
--s:,--origext: '$add@ ORIGEXTS'
@ -1178,17 +1447,24 @@ args=(
-V:,--version: version=
--auto-archive disttype=auto
-F,--full-archive disttype=full
-P,--patch-archive disttype=patch
-H,--patch-archive disttype=patch
--auto-unwrap unwrap=auto
--no-unwrap unwrap=
-E,--unwrap unwrap=1
-p,--patch action=patch
-a,--add-global action=add-global
-g,--patch action=patch
--ask-commit commit_policy=ask
-c,--comit commit_policy=1
--no-commit commit_policy=
-b,--add-global action=add-global
--locals action=list-locals
--profiles action=list-profiles
-s,--switch action=switch
-b,--add-local action=add-local
-a,--add-local action=add-local
-e,--edit action=edit
-p:,--profile: profile=
-P,--prod profile=prod
-T,--test profile=test
-A,--all-profiles profile=ALL
-d,--diff action=diff
--infos action=infos
-l,--list-names,--show-all alternate=1
@ -1199,14 +1475,14 @@ array_fix_paths ORIGEXTS
case "$action" in
init) init_cmd "$@";;
new) new_cmd "$autopatch" "$version" "$disttype" "$unwrap" "$@";;
patch) patch_cmd "$@";;
new) new_cmd "$autopatch" "$version" "$disttype" "$unwrap" "$commit_policy" "$@";;
patch) patch_cmd "$commit_policy" "$@";;
add-global) add_global_cmd "$@";;
list-locals) list_locals_cmd "$@";;
list-profiles) list_profiles_cmd "$@";;
switch) switch_cmd "$@";;
add-local) add_local_cmd "$@";;
edit) edit_cmd "$@";;
edit) edit_cmd "$profile" "$@";;
diff) diff_cmd "$alternate" "$@";;
infos) infos_cmd "$alternate" "$@";;
esac