nutools/prel

504 lines
18 KiB
Plaintext
Raw Normal View History

#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
if [ $# -eq 1 -a "$1" == --nutools-completion ]; then
echo '
function __prel_completion() {
local cur
_get_comp_words_by_ref cur
COMPREPLY=($(compgen -W "$(__prel_branches)" "$cur"))
}
complete -F __prel_completion prel
'
exit 0
fi
2015-03-23 07:56:32 +04:00
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
2015-02-19 16:25:06 +04:00
urequire DEFAULTS ptools
2015-03-23 07:56:32 +04:00
# XXX Ajouter une option pour fusionner les modifications d'une branche de
# pré-release dans develop
function display_help() {
uecho "$scriptname: basculer sur une branche de release
USAGE
2015-03-13 00:22:07 +04:00
$scriptname -u [SOURCE]
$scriptname -c [RELEASE [SOURCE]]
2015-03-13 00:22:07 +04:00
$scriptname -m|-l|-d [RELEASE]
- Vérifier s'il n'y a pas de modifications locales. Sinon, proposer de faire un
commit ou un stash.
2015-03-13 00:22:07 +04:00
- Avec l'option -c, s'il existe une branche de release, proposer de basculer
vers elle ou sur la branche master. Sinon, basculer sur la branche master.
2015-03-13 00:22:07 +04:00
- Avec l'option -u, proposer ou fixer une branche de release à créer. Si elle
existe déjà, basculer vers elle. Sinon, la créer en la basant sur SOURCE, qui
vaut par défaut develop
OPTIONS
-C, --projdir PROJDIR
Spécifier le répertoire de base du projet qui est dans git. Par défaut,
on travaille dans le répertoire courant et on laisse git trouver le
répertoire de base du projet. Avec cette option, le répertoire courant
est modifié avant de lancer les commandes git.
-O, --origin ORIGIN
Spécifier le nom de l'origine. Par défaut, utiliser 'origin'
-o, --offline
En cas de création d'une branche, ne pas pousser vers l'origine; ne pas
tenter le cas échéant de traquer la branche dans l'origine; ne pas
supprimer une branche dans l'origine. Cette option est automatiquement
activée si la variable UTOOLS_VCS_OFFLINE est définie.
--online
Annuler l'effet de la variable UTOOLS_VCS_OFFLINE: forcer le mode online
2015-03-13 00:22:07 +04:00
-c, --checkout
Basculer vers une branche de release existante. C'est l'option par
défaut. Si aucune branche de release n'existe, basculer vers master
-u, --update
2015-03-13 00:22:07 +04:00
Préparer une nouvelle release. Utiliser une des options -x, -z ou -p
pour spécifier le type de release à préparer. Si la branche qui serait
créée pour le type de release existe déjà, basculer vers cette branche.
S'il faut la créer, la baser sur la branche SOURCE, qui vaut par défaut
develop
--menu
-x, --major
-z, --minor
-p, --patchlevel
2015-03-13 00:22:07 +04:00
Utilisé avec l'option -u, soit afficher un menu pour choisir la version
de la nouvelle release (par défaut), soit préparer respectivement une
release majeure, mineure, ou pour correction de bug.
-v-OPT
Avec l'option -u, spécifier une option de pver permettant de choisir la
version de la nouvelle release. Les options supportées sont -v, -l, -a,
-b, -r et -R. Par exemple, si la version actuelle sur la branche master
est 0.2.3, les options '-uz -v-lbeta' permettent de préparer la release
0.3.0-beta
En principe, cette option n'a pas à être utilisée, puisque dans une
branche de release, on peut faire vivre les versions de pré-release
jusqu'à la release finale. Ainsi, la branche de release est nommée
d'après la version finale, mais le projet peut recevoir une version de
pré-release incrémentale.
2015-03-23 07:33:01 +04:00
-w, --write
Si une nouvelle branche est créée avec -u, mettre à jour le fichier
VERSION.txt avec pver. C'est l'option par défaut.
-n, --no-write
Si une nouvelle branche est créée avec -u, NE PAS mettre à jour le
fichier VERSION.txt avec pver. Utiliser cette option si la mise à jour
du numéro de version doit être faite d'une manière particulière.
-e, --edit
Editer le fichier CHANGES.txt autogénéré par -u -w
Cette option est surtout utile si -m est utilisé avec -u, pour donner la
possibilité de corriger la liste des modifications avant leur
enregistrement définitif.
2015-03-13 00:22:07 +04:00
-m, --merge
Si la branche actuelle est une branche de release, ou s'il existe une
branche de release, la merger dans master, puis dans develop, puis la
supprimer. Puis basculer sur la branche master.
S'il n'existe pas de branche de release, proposer de fusionner les
modifications de la branche develop dans la branche master, sans
préparer de branche de release au préalable.
--delete
Supprimer une branche de release, à condition qu'elle aie déjà été
entièrement fusionnée dans la branch master
--force-delete
2015-03-26 20:08:35 +04:00
Supprimer une branche de release, même si elle n'a pas encore été
fusionnée dans la branche master
-s, --summary
Afficher la liste des différences entre la branche develop et la branche
master, comme elle serait générée par les options -u -w pour le fichier
CHANGES.txt
-l, --log
Afficher les modifications actuellement effectuée dans la branche de
release par rapport à develop.
-d, --diff
Afficher les modifications actuellement effectuée dans la branche de
release par rapport à develop, sous forme de diff."
}
projdir=
origin=origin
action=auto
checkout=
2015-03-31 17:59:47 +04:00
update=
2015-03-13 00:22:07 +04:00
incversion=
pver_opts=()
2015-03-23 07:33:01 +04:00
write=1
edit_changes=
2015-03-31 17:59:47 +04:00
merge=
force_delete=
2015-03-13 00:22:07 +04:00
log=
diff=
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-C:,--projdir: projdir= \
-O:,--origin: origin= \
-o,--offline UTOOLS_VCS_OFFLINE=1 \
--online UTOOLS_VCS_OFFLINE= \
-c,--checkout checkout=1 \
-u,--update '$update=1; [ -z "$incversion" ] && incversion=auto' \
--menu '$update=1; incversion=menu' \
-x,--major '$update=1; incversion=major' \
-z,--minor '$update=1; incversion=minor' \
-p,--patchlevel '$update=1; incversion=patchlevel' \
-v: '$update=1; add@ pver_opts' \
2015-03-23 07:33:01 +04:00
-w,--write write=1 \
-n,--no-write write= \
-e,--edit edit_changes=1 \
-m,--merge merge=1 \
--delete action=delete \
--force-delete '$action=delete; force_delete=1' \
-s,--summary action=summary \
2015-03-13 00:22:07 +04:00
-l,--log '$action=diff; log=1' \
-d,--diff '$action=diff; diff=1' \
@ args -- "$@" && set -- "${args[@]}" || die "$args"
if [ "$action" == auto ]; then
if [ -n "$update" ]; then
action=update
elif [ -n "$merge" ]; then
action=merge
elif [ -n "$checkout" ]; then
action=checkout
2015-03-28 01:22:35 +04:00
else
# checkout par défaut
action=checkout
fi
fi
if [ -n "$projdir" ]; then
cd "$projdir" || die
fi
git_ensure_gitvcs
2015-03-13 00:22:07 +04:00
push_branches=()
push_tags=()
push_deferred=
[ -n "$UTOOLS_VCS_OFFLINE" ] && push_deferred= || push_deferred=1
[ -n "$update" -a -n "$merge" ] && UTOOLS_VCS_OFFLINE=1
2015-03-13 00:22:07 +04:00
setx branch=git_get_branch
2015-03-23 06:21:44 +04:00
if [ "$action" == update ]; then
2015-03-23 07:33:01 +04:00
setx oldver=pver -g ""
newver=
2015-03-23 06:21:44 +04:00
2015-03-23 06:34:59 +04:00
if [ "$incversion" == auto ]; then
2015-03-23 06:42:51 +04:00
if [ ${#pver_opts[*]} -gt 0 ]; then
# des options ont été spécifiées, les honorer
2015-03-23 07:33:01 +04:00
setx newver=pver -s "$oldver" "${pver_opts[@]}"
release="release-$newver"
2015-03-23 06:34:59 +04:00
else
2015-03-23 06:42:51 +04:00
# sinon, prendre une décision en fonction des branches de release
# qui existent déjà
2015-03-28 01:11:24 +04:00
setx -a branches=list_release_branches "$origin"
2015-03-23 06:42:51 +04:00
if [ ${#branches[*]} -eq 0 ]; then
# en l'absence de branche de release, proposer d'en créer une
incversion=menu
elif [ ${#branches[*]} -eq 1 ]; then
# s'il n'y en a qu'une, la prendre
release="${branches[0]}"
else
# sinon, donner le choix dans un menu
array_add branches master
default_branch="$branch"
array_contains branches "$default_branch" || default_branch="${branches[0]}"
simple_menu release branches -d "$default_branch" \
2015-03-28 01:04:57 +04:00
-t "Basculer vers une branche de release" \
2015-03-23 06:42:51 +04:00
-m "Veuillez choisir la branche vers laquelle basculer"
fi
2015-03-23 06:34:59 +04:00
fi
2015-03-23 06:21:44 +04:00
fi
case "$incversion" in
menu)
2015-03-23 07:33:01 +04:00
setx majorv=pver -s "$oldver" -ux "${pver_opts[@]}"
setx minorv=pver -s "$oldver" -uz "${pver_opts[@]}"
2015-04-12 12:30:12 +04:00
setx patchlevelv=pver -s "$oldver" -up "${pver_opts[@]}"
2015-03-23 06:42:51 +04:00
release="release-$minorv"
branches=("release-$majorv" "release-$minorv" "release-$patchlevelv" master)
2015-03-23 06:21:44 +04:00
simple_menu release branches \
2015-03-28 01:04:57 +04:00
-t "Basculer vers une nouvelle branche de release" \
2015-03-23 06:21:44 +04:00
-m "Veuillez choisir la branche à créer"
[ "$release" != master ] && newver="${release#release-}"
2015-03-23 06:21:44 +04:00
;;
major)
2015-03-23 07:33:01 +04:00
setx newver=pver -s "$oldver" -ux "${pver_opts[@]}"
release="release-$newver"
2015-03-23 06:21:44 +04:00
;;
minor)
2015-03-23 07:33:01 +04:00
setx newver=pver -s "$oldver" -uz "${pver_opts[@]}"
release="release-$newver"
2015-03-23 06:21:44 +04:00
;;
patchlevel)
2015-03-23 14:05:56 +04:00
setx newver=pver -s "$oldver" -up "${pver_opts[@]}"
2015-03-23 07:33:01 +04:00
release="release-$newver"
2015-03-23 06:21:44 +04:00
;;
esac
set -- "$release" "$1"
action=checkout
fi
2015-03-13 00:22:07 +04:00
if [ "$action" == checkout ]; then
release="$1"
source="${2:-develop}"
if [ -z "$release" ]; then
2015-03-28 01:11:24 +04:00
setx -a branches=list_release_branches "$origin"
2015-03-13 00:22:07 +04:00
if [ ${#branches[*]} -eq 0 ]; then
# en l'absence de branche de release, basculer sur master
release=master
elif [ ${#branches[*]} -eq 1 ]; then
# s'il n'y en a qu'une, la prendre
release="${branches[0]}"
2015-03-13 00:22:07 +04:00
else
# sinon, donner le choix dans un menu
2015-03-13 00:22:07 +04:00
array_add branches master
default_branch="$branch"
array_contains branches "$default_branch" || default_branch="${branches[0]}"
simple_menu release branches -d "$default_branch" \
2015-03-28 01:04:57 +04:00
-t "Basculer vers une branche de release" \
2015-03-13 00:22:07 +04:00
-m "Veuillez choisir la branche vers laquelle basculer"
fi
fi
# On est peut-être déjà sur la bonne branche
if git_is_branch "$release"; then
if [ -z "$UTOOLS_VCS_OFFLINE" ]; then
git_track_branch "$release" "$origin"
fi
2015-03-28 01:30:47 +04:00
git_fast_forward "$release" "" "$origin"
2015-03-13 00:22:07 +04:00
exit 0
fi
# Créer/basculer vers une release branch
git_ensure_cleancheckout
2015-03-28 01:04:57 +04:00
is_any_branch "$release" master release || die "$release: ce n'est pas une branche de release"
2015-03-23 07:33:01 +04:00
r=0
newbranch=
2015-03-13 00:22:07 +04:00
if git_have_branch "$release"; then
2015-03-23 07:33:01 +04:00
git checkout "$release"; r=$?
elif git_have_rbranch "$release"; then
git checkout "$release"; r=$?
2015-03-13 00:22:07 +04:00
else
estepn "\
2015-03-28 01:04:57 +04:00
Vous allez créer la nouvelle branche de release ${COULEUR_VERTE}$release${COULEUR_NORMALE}
2015-03-13 00:22:07 +04:00
à partir de la branche source ${COULEUR_BLEUE}$source${COULEUR_NORMALE}"
ask_yesno "Voulez-vous continuer?" O || die
newbranch=1
2015-03-13 00:22:07 +04:00
git_ensure_branch "$release" "$source" "$origin"
[ $? -eq 2 ] && die "Impossible de créer la branche $release. Veuillez vérifier que la branche $source existe"
2015-03-23 07:33:01 +04:00
git checkout "$release"; r=$?
if [ -z "$newver" ]; then
# le cas échéant, tenter de calculer la version en fonction de la release
is_release_branch "$release" && newver="${release#release-}"
fi
if [ "$r" -eq 0 -a -n "$write" ]; then
set cwd=pwd
setx workdir=git rev-parse --show-toplevel
[ -d "$workdir" ] && cd "$workdir"
commitmsg="Init changelog"
if [ -n "$newver" ]; then
pver -uv "$newver" && commitmsg="Init changelog & version $newver"
fi
version="$newver"
[ -n "$version" ] || version="$release"
changelog="## Version $version du $(date +%d/%m/%Y-%H:%M)"
setx mergebase=git merge-base master "$release"
setxp modifs=git log --oneline "$mergebase..$release" // grep -v "Intégration de la branche release-"
[ -n "$modifs" ] && changelog="$changelog
$modifs"
ac_set_tmpfile tmpchanges
echo "$changelog" >>"$tmpchanges"
if [ -n "$edit_changes" ]; then
estep "Lancement d'un éditeur pour vérifier la liste des modifications"
"${EDITOR:-vi}" "$tmpchanges"
2015-03-23 07:33:01 +04:00
fi
if [ -f CHANGES.txt ]; then
echo >>"$tmpchanges"
cat CHANGES.txt >>"$tmpchanges"
fi
cat "$tmpchanges" >CHANGES.txt
ac_clean "$tmpchanges"
git add -A
git commit -m "$commitmsg"
cd "$cwd"
2015-03-23 07:33:01 +04:00
fi
fi
2015-03-28 01:30:47 +04:00
if [ "$r" -eq 0 ]; then
# éventuellement fast-forwarder automatiquement
git_fast_forward "$release" "" "$origin"
fi
2015-03-23 07:33:01 +04:00
set -- "$release"
if [ "$r" -eq 0 -a -n "$merge" ]; then
2015-03-31 17:59:47 +04:00
# mettre à jour la branche sur laquelle on se trouve
setx branch=git_get_branch
action=merge
elif [ "$r" -eq 0 -a -n "$newbranch" ]; then
action=push
array_addu push_branches "$release"
else
exit "$r"
fi
2015-03-23 07:33:01 +04:00
fi
setx -a branches=list_release_branches
setb have_release_branches=[ ${#branches[*]} -gt 0 ]
release="$1"
if [ -n "$release" ]; then
if [ -n "$have_release_branches" ]; then
2015-03-28 01:04:57 +04:00
is_release_branch "$release" || die "$release: ce n'est pas une branche de release"
2015-03-23 07:33:01 +04:00
elif ! is_develop_branch "$release"; then
die "Aucune branche de release n'existe, vous devez fusionner à partir de develop"
fi
2015-03-31 17:59:47 +04:00
git_have_branch "$release" || die "$release: branche introuvable"
2015-03-23 07:33:01 +04:00
elif is_release_branch "$branch"; then
release="$branch"
fi
if [ "$action" == merge ]; then
confirm=
if [ -z "$release" ]; then
if [ ${#branches[*]} -eq 0 ]; then
2015-03-28 01:04:57 +04:00
ewarn "Aucune branche de release n'a été préparée."
ewarn "La branche develop sera fusionnée directement dans master."
2015-03-23 07:33:01 +04:00
release=develop
confirm=-y
elif [ ${#branches[*]} -eq 1 ]; then
release="${branches[0]}"
estepn "Autosélection de $release"
else
default_release="$branch"
array_contains branches "$default_release" || default_release="${branches[0]}"
simple_menu release branches -d "$default_release" \
2015-03-28 01:04:57 +04:00
-t "Choix de la branche de release" \
2015-03-23 07:33:01 +04:00
-m "Veuillez choisir la branche"
fi
fi
2015-03-23 13:51:06 +04:00
estepn "Intégration ${COULEUR_VERTE}$release${COULEUR_NORMALE} --> ${COULEUR_BLEUE}master${COULEUR_NORMALE}"
2015-03-23 07:33:01 +04:00
ask_yesno $confirm "Voulez-vous continuer?" O || die
2015-03-31 17:59:47 +04:00
git checkout master || die
git merge "$release" -m "Intégration de la branche $release" --no-ff || die
2015-03-23 07:33:01 +04:00
2015-03-31 18:53:32 +04:00
if [ -z "$newver" ]; then
# le cas échéant, tenter de calculer la version en fonction de la release
is_release_branch "$release" && newver="${release#release-}"
fi
if [ -n "$newver" ]; then
2015-03-31 18:53:32 +04:00
estepn "Création du tag $newver"
array_addu push_tags "$newver"
git tag --force "$newver" || die
2015-04-16 10:54:47 +04:00
if git_have_remote "$origin"; then
if [ -z "$UTOOLS_VCS_OFFLINE" ]; then
git push "$origin" tag "$newver"
elif [ -z "$push_deferred" ]; then
2015-04-16 10:54:47 +04:00
eimportant "Le tag $newver n'a pas été poussé vers l'origine.
Il faudra le faire manuellement avec la commande suivante:
$(qvals git push "$origin" tag "$newver")
ou celle-ci pour pour pousser TOUS les tags:
$(qvals git push "$origin" --tags)"
fi
fi
fi
2015-03-23 07:33:01 +04:00
if [ "$release" != develop ]; then
2015-03-23 13:51:06 +04:00
estepn "Intégration ${COULEUR_VERTE}$release${COULEUR_NORMALE} --> ${COULEUR_BLEUE}develop${COULEUR_NORMALE}"
2015-03-23 07:33:01 +04:00
git checkout develop
git merge "$release" -m "Intégration de la branche $release" --no-ff || die
2015-03-31 17:59:47 +04:00
fi
2015-03-23 07:33:01 +04:00
2015-03-31 17:59:47 +04:00
# mettre à jour la branche sur laquelle on se trouve
git checkout master || die
setx branch=git_get_branch
2015-03-23 07:33:01 +04:00
2015-03-31 18:53:32 +04:00
action=delete
2015-03-31 17:59:47 +04:00
fi
2015-03-23 07:33:01 +04:00
2015-04-01 12:34:02 +04:00
if [ "$action" == delete -a "$release" != develop ]; then
2015-03-31 17:59:47 +04:00
if [ -z "$force_delete" ]; then
# vérifier que la branche a été fusionnée
git_is_merged "$release" master || die "Refus de supprimer la branche $release: elle n'a pas été fusionnée dans master"
git_is_merged "$release" develop || die "Refus de supprimer la branche $release: elle n'a pas été fusionnée dans develop"
fi
if [ "$branch" == "$release" ]; then
# si on est sur la branche en question, en sortir pour pouvoir la
# supprimer
git checkout master || die
fi
estepi "Suppression de la branche locale"
git branch -D "$release"
if git_have_remote "$origin"; then
if [ -z "$UTOOLS_VCS_OFFLINE" ]; then
estepi "Suppression de la branche distante"
git push "$origin" ":$release"
elif git_have_rbranch "$release" "$origin"; then
eimportant "\
La branche $origin/$release n'a plus lieu d'être, mais la configuration actuelle interdit de la supprimer.
2015-03-23 07:33:01 +04:00
Veuillez le faire manuellement avec la commande suivante:
2015-03-23 07:36:28 +04:00
$(qvals git push "$origin" ":$release")"
2015-03-23 07:33:01 +04:00
fi
2015-03-13 00:22:07 +04:00
fi
action=push
array_addu push_branches master
array_addu push_branches develop
fi
if [ "$action" == push -a -n "$push_deferred" ]; then
if git_have_remote "$origin"; then
estepi "Mise à jour de l'origine"
for tag in "${push_tags[@]}"; do
git push "$origin" tag "$tag"
done
for branch in "${push_branches[@]}"; do
setx rbranch=git_get_branch_rbranch "$branch" "$origin"
rbranch="${rbranch#refs/remotes/$origin/}"
git push "$origin" "$branch:$rbranch"
done
fi
2015-03-31 17:59:47 +04:00
fi
2015-03-13 00:22:07 +04:00
if [ "$action" == summary ]; then
setx mergebase=git merge-base master develop
2015-05-22 13:35:41 +04:00
git log --oneline "$mergebase..develop" | grep -v "Intégration de la branche release-"
elif [ "$action" == diff ]; then
2015-03-23 07:33:01 +04:00
if [ -n "$log" ]; then
if [ -n "$release" ]; then
git log ${diff:+-p} master.."$release"
else
git log ${diff:+-p} master..develop
fi
elif [ -n "$diff" ]; then
if [ -n "$release" ]; then
git diff master.."$release"
else
git diff master..develop
fi
fi
2015-03-13 00:22:07 +04:00
fi