# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # configuration par défaut # doit être identique au contenu de pman.conf # les branches sont mergées dans cet ordre: # upstream --> develop --> [release -->] main --> dist # feature _/ hotfix _/ # branche upstream UPSTREAM= # branches de développement DEVELOP=develop FEATURE=wip/ # branche de préparation de release RELEASE=release- # branche de release MAIN=master TAG_PREFIX= TAG_SUFFIX= # branche de hotfix HOTFIX=hotfix- # branche de distribution DIST= # désactiver les releases automatiques? NOAUTO= CONFIG_VARS=( UPSTREAM DEVELOP FEATURE RELEASE MAIN TAG_PREFIX TAG_SUFFIX HOTFIX DIST NOAUTO ) PMAN_TOOL_PUPS=UPSTREAM PMAN_TOOL_PDEV=DEVELOP PMAN_TOOL_PWIP=FEATURE PMAN_TOOL_PMAIN=MAIN PMAN_TOOL_PDIST=DIST UPSTREAM_CREATE_BASE= ; UPSTREAM_MERGE_FROM= ; UPSTREAM_MERGE_TO=DEVELOP ; UPSTREAM_PREL= ; UPSTREAM_DELETE= DEVELOP_CREATE_BASE=MAIN ; DEVELOP_MERGE_FROM=FEATURE ; DEVELOP_MERGE_TO=MAIN ; DEVELOP_PREL=to ; DEVELOP_DELETE=from MAIN_CREATE_BASE= ; MAIN_MERGE_FROM=DEVELOP ; MAIN_MERGE_TO=DIST ; MAIN_PREL=from ; MAIN_DELETE= DIST_CREATE_BASE=MAIN ; DIST_MERGE_FROM=MAIN ; DIST_MERGE_TO= ; DIST_PREL= ; DIST_DELETE= FEATURE_CREATE_BASE=DEVELOP ; FEATURE_MERGE_FROM= ; FEATURE_MERGE_TO=DEVELOP ; FEATURE_PREL= ; FEATURE_DELETE=to function get_create_base() { # afficher la branche depuis laquelle créer la branche $1 # retourner 1 en cas d'erreur (pas de branche source) local branch="$1" infos [ -n "$branch" ] || return 1 infos="${branch^^}_CREATE_BASE"; branch="${!infos}" [ -n "$branch" ] && echo "$branch" || return 1 } function get_merge_from() { # afficher la branche depuis laquelle la branche $1 doit merger # retourner 1 en cas d'erreur (pas de branche source) local branch="$1" infos [ -n "$branch" ] || return 1 infos="${branch^^}_MERGE_FROM"; branch="${!infos}" [ -n "$branch" ] && echo "$branch" || return 1 } function get_merge_to() { # afficher la branche dans laquelle la branche $1 doit merger # retourner 1 en cas d'erreur (pas de branche destination) local branch="$1" infos [ -n "$branch" ] || return 1 infos="${branch^^}_MERGE_TO"; branch="${!infos}" [ -n "$branch" ] && echo "$branch" || return 1 } function should_prel_merge() { # tester si la branche $1 doit être mergée avec prel dans la direction # $2(=to) local branch="$1" dir="${2:-to}" infos [ -n "$branch" ] || return 1 infos="${branch^^}_PREL" [ "${!infos}" == "$dir" ] } function should_delete_merged() { # tester si la branche $1 doit être supprimée après avoir été mergée dans la # direction $2(=to) local branch="$1" dir="${2:-to}" infos [ -n "$branch" ] || return 1 infos="${branch^^}_DELETE" [ "${!infos}" == "$dir" ] } function _init_changelog() { setx date=date +%d/%m/%Y-%H:%M ac_set_tmpfile changelog echo >"$changelog" "\ Vérifiez et complétez la liste des changements le cas échéant. Un fichier vide annule l'opération Ces lignes ne seront pas incluses dans le fichier destination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " } function _filter_rel() { # enlever les commits "techniques" générés par ce script awk ' BEGIN { tech = 0 } tech == 0 && $0 ~ /^\+.*/ { tech = 1; next } tech == 1 && $0 ~ /^\|/ { next } tech == 1 && $0 ~ /^\+/ { tech = 0 } $0 !~ // { print } ' } function _filter_changes() { # enlever les commits "inutiles" pour générer le fichier CHANGES.md grep -vE '^([+|] )?[0-9a-f]+ modifs\.mineures sans commentaires$' | grep -vE '^([+|] )?[0-9a-f]+ (cosmetic|typo|bug|fix|maj projet|maj deps)$' } function _format_md() { awk ' $0 == "" || $0 ~ /^#/ { print; next } $1 == "+" { $1 = "*" $2 = "`" $2 "`" print; next } $1 == "|" { $1 = " *" $2 = "`" $2 "`" print; next } { $1 = "* `" $1 "`" print; next } ' } function _list_commits() { local source="${1:-$SrcBranch}" dest="${2:-$DestBranch}" mergebase setx mergebase=git merge-base "$dest" "$source" git log --oneline --graph --no-decorate "$mergebase..$source" | grep -vF '|\' | grep -vF '|/' | sed -r 's/^(\| )+\* +/| /; s/^\* +/+ /' | _filter_rel } function _show_diff() { local source="${1:-$SrcBranch}" dest="${2:-$DestBranch}" mergebase setx mergebase=git merge-base "$dest" "$source" git diff ${_sd_COLOR:+--color=$_sd_COLOR} "$mergebase..$source" } function _scripte() { echo >>"$script" echo "$comment$(qvals "$@")" >>"$script" } function _scripta() { [ $# -gt 0 ] && _scripte einfo "$*" cat >>"$script" } function _script_push_branches() { [ ${#push_branches[*]} -gt 0 ] || return [ -n "$Origin" ] || Origin=origin git_have_remote "$Origin" || return local branch cmd remote rbranch for branch in "${push_branches[@]}"; do if [[ "$branch" == *:* ]]; then cmd="$(qvals git push "$Origin" "$branch")" else setx remote=git_get_branch_remote "$branch" if [ "$remote" == "$Origin" ]; then setx rbranch=git_get_branch_merge "$branch" if [ -n "$rbranch" ]; then # pousser vers la branche distante existante cmd="$(qvals git push "$Origin" "$branch:${rbranch#refs/heads/}")" else # pas de branche distante: pousser et traquer cmd="$(qvals git push -u "$Origin" "$branch:$branch")" fi elif [ -n "$remote" ]; then # pousser vers un remote différent cmd="$(qvals git push "$Origin" "$branch:$branch")" else # pas de remote: pousser et traquer cmd="$(qvals git push -u "$Origin" "$branch:$branch")" fi fi _scripta <<<"$comment$cmd$or_die" done } function _script_push_tags() { local origin tag _scripte einfo "push tags" for tag in "${push_tags[@]}"; do origin="$Origin" [ -n "$origin" ] || origin=origin _scripta <"$config" 2>/dev/null [ -s "$config" ] || die "$ConfigBranch: aucune configuration trouvée sur cette branche" || return source "$config" fi elif [ -f .pman.conf ]; then ConfigFile="$(pwd)/.pman.conf" source "$ConfigFile" else ConfigFile="$NULIBDIR/bash/src/pman.conf.sh" fi # S'assurer que nulib est dans le PATH pour que les scripts utilisateurs # puissent utiliser les outils fournis export PATH="$NULIBDIR/bin:$PATH" } ################################################################################ # Divers function resolve_should_push() { local quiet="$1" ShouldPush=1 if ! git_have_remote "$Origin" && [ -n "$Push" ]; then [ -n "$quiet" ] || enote "L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine" ShouldPush= fi [ -z "$ShouldPush" ] && Push= } function _push_branches() { [ ${#push_branches[*]} -gt 0 ] || return [ -n "$Origin" ] || Origin=origin git_have_remote "$Origin" || return local -a cmds; local branch cmd remote rbranch for branch in "${push_branches[@]}"; do if [[ "$branch" == *:* ]]; then cmds+=("$(qvals git push "$Origin" "$branch")") else setx remote=git_get_branch_remote "$branch" if [ "$remote" == "$Origin" ]; then setx rbranch=git_get_branch_merge "$branch" if [ -n "$rbranch" ]; then # pousser vers la branche distante existante cmds+=("$(qvals git push "$Origin" "$branch:${rbranch#refs/heads/}")") else # pas de branche distante: pousser et traquer cmds+=("$(qvals git push -u "$Origin" "$branch:$branch")") fi elif [ -n "$remote" ]; then # pousser vers un remote différent cmds+=("$(qvals git push "$Origin" "$branch:$branch")") else # pas de remote: pousser et traquer cmds+=("$(qvals git push -u "$Origin" "$branch:$branch")") fi fi done [ -n "$Push" ] || enote "L'option --no-push étant utilisée, les opérations à effectuer sont simplement affichées" for cmd in "${cmds[@]}"; do einfo "$cmd" if [ -n "$Push" ]; then if ! eval "$cmd"; then ewarn "Une erreur s'est produite, les opérations seront simplement affichées" Push= fi fi done } ################################################################################ # Merge function _mscript_start() { >"$script" _scripta <"$script" _scripta <>"$changelog" "\ ## Release $Tag du $date " _list_commits | _filter_changes | _format_md >>"$changelog" "${EDITOR:-nano}" +7 "$changelog" [ -s "$changelog" ] || exit_with ewarn "Création de la release annulée" # créer la branche de release et basculer dessus _scripta "create branch $ReleaseBranch" <"\$tmpchanges" if [ -s CHANGES.md ]; then echo >>"\$tmpchanges" cat CHANGES.md >>"\$tmpchanges" fi cat "\$tmpchanges" >CHANGES.md rm -f "\$tmpchanges" git add CHANGES.md EOF # mettre à jour la version _scripta "update VERSION.txt" <VERSION.txt git add VERSION.txt EOF # Enregistrer les changements _scripta "commit" <Init changelog & version $Tag") EOF } function _rscript_merge_release_branch() { local dest="$1" tag="$2" # basculer sur la branche _scripta "switch to branch $dest" <Intégration de la branche $ReleaseBranch" --no-ff)$or_die EOF array_addu push_branches "$dest" # tagger la release if [ -n "$tag" ]; then _scripta "create tag $tag" <