diff --git a/bash/src/git.sh b/bash/src/git.sh index a879f28..b893864 100644 --- a/bash/src/git.sh +++ b/bash/src/git.sh @@ -36,6 +36,11 @@ NULIB_GIT_FUNCTIONS_MAP=( im:git_is_merged ) +function: git_get_toplevel "" +function git_get_toplevel() { + git rev-parse --show-toplevel 2>/dev/null +} + function: git_check_gitvcs "" function git_check_gitvcs() { git rev-parse --show-toplevel >&/dev/null @@ -43,7 +48,7 @@ function git_check_gitvcs() { function: git_ensure_gitvcs "" function git_ensure_gitvcs() { - git_check_gitvcs || edie "Ce n'est pas un dépôt git" || return + git_check_gitvcs || die "$(ppath "$(pwd)" ~): ce répertoire n'est pas un dépôt git" || return } function: git_list_branches "" @@ -160,10 +165,14 @@ function git_check_cleancheckout() { [ -z "$(git status --porcelain 2>/dev/null)" ] } +git_cleancheckout_VERBOSE=1 +git_cleancheckout_DIRTY="Vous avez des modifications locales. Enregistrez ces modifications avant de continuer" function: git_ensure_cleancheckout "" function git_ensure_cleancheckout() { - git_check_cleancheckout || - edie "Vous avez des modifications locales. Enregistrez ces modifications avant de continuer" || return + git_check_cleancheckout && return + [ -n "$git_cleancheckout_VERBOSE" ] && + git status --porcelain 2>/dev/null + die "$git_cleancheckout_DIRTY" || return } function git__init_ff() { diff --git a/wip/_rel b/wip/_rel index cd63357..51d657b 100755 --- a/wip/_rel +++ b/wip/_rel @@ -3,6 +3,11 @@ source "$(dirname -- "$0")/../load.sh" || exit 1 require: git +git_cleancheckout_DIRTY="\ +Vous avez des modifications locales. +Enregistrez ces modifications avant de créer une release" + +# configuration par défaut UPSTREAM= DEVELOP=develop FEATURE=wip/ @@ -11,58 +16,414 @@ MAIN=master TAG_SUFFIX= HOTFIX=hotfix- DIST= -source "$MYDIR/pman${MYNAME#_rel}.conf" +NOAUTO= + +function load_config() { + [ -z "$Config" -a -f .pman.conf ] && Config=.pman.conf + if [ -n "$Config" ]; then + source "$Config" + else + source "$MYDIR/pman${MYNAME#_rel}.conf" + fi + + setx CurrentBranch=git_get_branch + SrcBranch="$1" + [ -n "$SrcBranch" ] || SrcBranch="$CurrentBranch" + case "$SrcBranch" in + "$UPSTREAM") SrcType=upstream; DestBranch="$DEVELOP";; + "$FEATURE"*) SrcType=feature; DestBranch="$DEVELOP";; + "$DEVELOP") SrcType=develop; DestBranch="$MAIN";; + "$RELEASE"*) SrcType=release; DestBranch="$MAIN";; + "$HOTFIX"*) SrcType=hotfix; DestBranch="$MAIN";; + "$MAIN") SrcType=main; DestBranch="$DIST";; + "$DIST") SrcType=dist; DestBranch=;; + *) DestBranch=;; + esac +} + +function ensure_branches() { + [ -n "$SrcBranch" -a -n "$DestBranch" ] || + die "$SrcBranch: Aucune configuration de fusion trouvée pour cette branche" + + setx -a Branches=git_list_pbranches "$Origin" + array_contains Branches "$SrcBranch" || die "$SrcBranch: branche source introuvable" + array_contains Branches "$DestBranch" || die "$DestBranch: branche destination introuvable" + + local branch + ReleaseBranch= + for branch in "${Branches[@]}"; do + if [[ "$branch" == "$RELEASE"* ]]; then + ReleaseBranch="$branch" + fi + done +} function init_action() { : } -function list_action() { - : +function _filter_rel() { + # enlever les commits "techniques" générés par ce script + grep -v "Intégration de la branche $RELEASE" | + grep -v "Branche $DEVELOP en version .*-SNAPSHOT" +} + +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 "$mergebase..$source" | + grep -vF '|\' | grep -vF '|/' | sed 's/\* //; s/^ /+ /' | + _filter_rel +} + +function show_action() { + local commits + setx commits=_list_commits + if [ -n "$commits" ]; then + einfo "Commits à fusionner $SrcBranch --> $DestBranch" + eecho "$commits" + fi +} + +function merge_action() { + die "action non implémentée" +} + +function _script_echo() { + echo >>"$script" + echo "$comment$(qvals echo "$@")" >>"$script" +} + +function _script_add() { + [ $# -gt 0 ] && _script_echo "$*" + cat >>"$script" +} + +function _script_start() { + >"$script" + _script_add <"$changelog" "\ +Vérifiez et complétez la liste des changements le cas échéant. +Un fichier vide annule la création de la release +Ces lignes ne seront pas incluses dans le fichier destination +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +" } function release_action() { - : + local script=".git/rel-release.sh" + local release="${RELEASE}$Version" + local date changelog + local -a push_branches push_tags + + case "$SrcType" in + hotfix) + enote "\ +Vous allez intégrer la branche de hotfix ${COULEUR_BLEUE}$SrcBranch${COULEUR_NORMALE} +dans la branche destination ${COULEUR_VERTE}$DestBranch${COULEUR_NORMALE}" + ask_yesno "Voulez-vous continuer?" O || die + + _init_changelog + echo "## Hotfix $Version du $date" >>"$changelog" + ;; + release) + enote "\ +Vous allez intégrer la branche de release ${COULEUR_BLEUE}$SrcBranch${COULEUR_NORMALE} +dans la branche destination ${COULEUR_VERTE}$DestBranch${COULEUR_NORMALE}" + ask_yesno "Voulez-vous continuer?" O || die + ;; + esac +} + +function release_upstream_action() { + merge_action "$@" +} + +function release_feature_action() { + merge_action "$@" +} + +function _create_release_branch() { + local date changelog + + _init_changelog + echo >>"$changelog" "\ +## Release $Version 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" + + _script_start + + # créer la branche de release et basculer dessus + _script_add "* create branch $ReleaseBranch" <>CHANGES.md +$(qvals echo "$(awk <"$changelog" ' +BEGIN { p = 0 } +p == 0 && $0 == "" { p = 1; next } +p == 1 { gsub(/\$/, "\\$", $0); print } +')") >>CHANGES.md +git add CHANGES.md +EOF + + # mettre à jour la version + _script_add "* update VERSION.txt" <VERSION.txt +git add VERSION.txt +EOF + + # Enregistrer les changements + _script_add "* commit" <