diff --git a/bash/src/pman.sh b/bash/src/pman.sh index 2d26133..917969c 100644 --- a/bash/src/pman.sh +++ b/bash/src/pman.sh @@ -147,18 +147,23 @@ EOF ################################################################################ # Config -function ensure_gitdir() { +function check_gitdir() { # commencer dans le répertoire indiqué local chdir="$1" if [ -n "$chdir" ]; then - cd "$chdir" || die || return + cd "$chdir" || return 1 fi # se mettre à la racine du dépôt git local gitdir git_ensure_gitvcs setx gitdir=git_get_toplevel - cd "$gitdir" || die || return + cd "$gitdir" || return 1 +} + +function ensure_gitdir() { + # commencer dans le répertoire indiqué + check_gitdir "$@" || die || return } function load_branches() { @@ -245,6 +250,9 @@ function load_config() { ConfigFile="$(pwd)/.pman.conf" source "$ConfigFile" elif [ -n "$1" -a -n "${MYNAME#$1}" ]; then + # $1 est le nom de base de l'outil e.g "pdev", et le suffixe est la + # configuration à charger par défaut. i.e pdev74 chargera par défaut la + # configuration pman74.conf ConfigFile="$NULIBDIR/bash/src/pman${MYNAME#$1}.conf.sh" source "$ConfigFile" else diff --git a/bash/src/pman.tool.pdev.sh b/bash/src/pman.tool.pdev.sh new file mode 100644 index 0000000..a913374 --- /dev/null +++ b/bash/src/pman.tool.pdev.sh @@ -0,0 +1,10 @@ +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +PMAN_TOOLS=pdev +SRC_TYPE=DEVELOP +SRC_BRANCH="${SRC_TYPE,,}"; SRC_BRANCH="${SRC_BRANCH^}Branch" +DEST_TYPE=MAIN +DEST_BRANCH="${DEST_TYPE,,}"; DEST_BRANCH="${DEST_BRANCH^}Branch" +ALLOW_MERGE=1 +MERGE_PREL=1 +ALLOW_DELETE= diff --git a/bash/src/pman.tool.pdist.sh b/bash/src/pman.tool.pdist.sh new file mode 100644 index 0000000..433e3bc --- /dev/null +++ b/bash/src/pman.tool.pdist.sh @@ -0,0 +1,10 @@ +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +PMAN_TOOL=pdist +SRC_TYPE=DIST +SRC_BRANCH="${SRC_TYPE,,}"; SRC_BRANCH="${SRC_BRANCH^}Branch" +DEST_TYPE= +DEST_BRANCH= +ALLOW_MERGE= +MERGE_PREL= +ALLOW_DELETE= diff --git a/bash/src/pman.tool.pmain.sh b/bash/src/pman.tool.pmain.sh new file mode 100644 index 0000000..3e6a4a0 --- /dev/null +++ b/bash/src/pman.tool.pmain.sh @@ -0,0 +1,10 @@ +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +PMAN_TOOL=pmain +SRC_TYPE=MAIN +SRC_BRANCH="${SRC_TYPE,,}"; SRC_BRANCH="${SRC_BRANCH^}Branch" +DEST_TYPE=DIST +DEST_BRANCH="${DEST_TYPE,,}"; DEST_BRANCH="${DEST_BRANCH^}Branch" +ALLOW_MERGE=1 +MERGE_PREL= +ALLOW_DELETE= diff --git a/bin/nlshell b/bin/nlshell index f5f64f6..6a628cd 100755 --- a/bin/nlshell +++ b/bin/nlshell @@ -20,8 +20,8 @@ fi [ -f /etc/profile ] && source /etc/profile [ -f ~/.bash_profile ] && source ~/.bash_profile -# Modifier le PATH. Ajouter aussi le chemin vers les uapps python -PATH=$(qval "$NULIBDIR/bin:$PATH") +# Modifier le PATH +PATH=$(qval "$NULIBDIR/wip:$NULIBDIR/bin:$PATH") if [ -n '$DEFAULT_PS1' ]; then DEFAULT_PS1=$(qval "[nlshell] $DEFAULT_PS1") diff --git a/wip/_pman.tool b/wip/_pman.tool new file mode 100755 index 0000000..3781dd6 --- /dev/null +++ b/wip/_pman.tool @@ -0,0 +1,372 @@ +#!/bin/bash +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +source "$(dirname -- "$0")/../load.sh" || exit 1 +require: git pman pman.conf "pman.tool.$MYNAME" + +git_cleancheckout_DIRTY="\ +Vous avez des modifications locales. +Enregistrez ces modifications avant de fusionner la branche" + +function dump_action() { + echo -n "\ +SRC_TYPE=$SRC_TYPE +SRC_BRANCH=$SRC_BRANCH +DEST_TYPE=$DEST_TYPE +DEST_BRANCH=$DEST_BRANCH + +CurrentBranch=$CurrentBranch +LocalBranches=${LocalBranches[*]} +RemoteBranches=${RemoteBranches[*]} +AllBranches=${AllBranches[*]} + +SrcType=$SrcType +SrcBranch=$SrcBranch +DestType=$DestType +DestBranch=$DestBranch + +UpstreamBranch=$UpstreamBranch +FeatureBranches=${FeatureBranches[*]} +DevelopBranch=$DevelopBranch +ReleaseBranch=$ReleaseBranch +HotfixBranch=$HotfixBranch +MainBranch=$MainBranch +DistBranch=$DistBranch +" +} + +function _ensure_src_branch() { + [ -n "$SrcBranch" ] || die "La branche $SRC_TYPE n'a pas été définie" + [ "$1" == init -o -n "${!SRC_BRANCH}" ] || die "$SrcBranch: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" +} + +function _ensure_dest_branch() { + [ -n "$DestBranch" ] || die "La branche $DEST_TYPE n'a pas été définie" + [ "$1" == init -o -n "${!DEST_BRANCH}" ] || die "$DestBranch: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" +} + +function checkout_action() { + local -a push_branches + + if [ -z "${!SRC_BRANCH}" ]; then + array_contains AllBranches "$SrcBranch" && exit_with enote "\ +$SrcBranch: une branche du même nom existe dans l'origine + git checkout $SrcBranch" + _ensure_dest_branch + _ensure_src_branch init + + resolve_should_push + + enote "Vous allez créer la branche ${COULEUR_BLEUE}$SrcBranch${COULEUR_NORMALE} <-- ${COULEUR_ROUGE}$DestBranch${COULEUR_NORMALE}" + ask_yesno "Voulez-vous continuer?" O || die + + einfo "Création de la branche $SrcBranch" + git checkout -b "$SrcBranch" "$DestBranch" || die + push_branches+=("$SrcBranch") + + _push_branches + fi + git checkout "$SrcBranch" +} + +function ensure_branches() { + [ -n "${!SRC_BRANCH}" -a -n "${!DEST_BRANCH}" ] || + die "${!SRC_BRANCH}: Aucune configuration de fusion trouvée pour cette branche" + + array_contains LocalBranches "${!SRC_BRANCH}" || die "${!SRC_BRANCH}: branche source introuvable" + array_contains LocalBranches "${!DEST_BRANCH}" || die "${!DEST_BRANCH}: branche destination introuvable" +} + +function _show_action() { + local commits + setx commits=_list_commits + if [ -n "$commits" ]; then + if [ $ShowLevel -ge 2 ]; then + { + echo "\ +# Commits à fusionner ${!SRC_BRANCH} --> ${!DEST_BRANCH} + +$commits +" + _sd_COLOR=always _show_diff + } | less -eRF + else + einfo "Commits à fusionner ${!SRC_BRANCH} --> ${!DEST_BRANCH}" + eecho "$commits" + fi + fi +} +function show_action() { + git_check_cleancheckout || ewarn "$git_cleancheckout_DIRTY" + ensure_branches + _show_action "$@" +} + +function _merge_action() { + enote "\ +Ce script va +- fusionner la branche ${COULEUR_BLEUE}${!SRC_BRANCH}${COULEUR_NORMALE} dans ${COULEUR_ROUGE}${!DEST_BRANCH}${COULEUR_NORMALE}${Push:+ +- pousser les branches modifiées}" + ask_yesno "Voulez-vous continuer?" O || die + + local script=".git/pman-merge.sh" + local -a push_branches delete_branches + local hook + local comment= + local or_die=" || exit 1" + + _mscript_start + _scripta <.gitignore "\ +.~lock*# +.*.swp" + git add .gitignore + fi + return 0 +} + +function init_repo_action() { + local -a push_branches; local config + + [ ${#LocalBranches[*]} -eq 0 ] || die "Ce dépôt a déjà été initialisé" + + _init_config || exit_with ewarn "Initialisation du dépôt annulée" + + einfo "Création de la branche $MAIN" + git symbolic-ref HEAD "refs/heads/$MAIN" + git commit -m "commit initial" + push_branches+=("$MAIN") + + einfo "Création de la branche $DEVELOP" + git checkout -b "$DEVELOP" + push_branches+=("$DEVELOP") + + _push_branches +} + +function init_config_action() { + local -a push_branches; local config + + [ -f .pman.conf -a -z "$ForceCreate" ] && die "La configuration pman a déjà été initialisée" + + resolve_should_push + + _init_config || exit_with ewarn "Initialisation de la configuration annulée" + git commit -m "configuration pman" + push_branches+=("$CurrentBranch") + + _push_branches +} + +function _init_composer() { + if [ ! -f .composer.pman.yml -o -n "$ForceCreate" ]; then + ac_set_tmpfile config + cat >"$config" <Intégration initiale de la branche $UPSTREAM" \ + -srecursive -Xours --allow-unrelated-histories \ + "$UPSTREAM" + push_branches+=("$DEVELOP") + + _push_branches + fi + git checkout -q "$UPSTREAM" +} + +function _ensure_dist_branch() { + [ -n "$DIST" ] || die "La branche DIST n'a pas été définie" + [ "$1" == init -o -n "$DistBranch" ] || die "$DIST: cette branche n'existe pas (le dépôt a-t-il été initialisé?)" +} + +function init_dist_action() { + local -a push_branches + + if [ -z "$DistBranch" ]; then + array_contains AllBranches "$DIST" && exit_with enote "\ +$DIST: une branche du même nom existe dans l'origine + git checkout $DIST" + _ensure_main_branch + _ensure_dist_branch init + + resolve_should_push + + enote "Vous allez créer la branche ${COULEUR_VERTE}$DIST${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$MAIN${COULEUR_NORMALE}" + ask_yesno "Voulez-vous continuer?" O || die + + einfo "Création de la branche $DIST" + git checkout -b "$DIST" "$MAIN" || die + push_branches+=("$DIST") + + _push_branches + fi + git checkout -q "$DIST" +} + +function init_feature_action() { + local -a push_branches; local branch + + [ -n "$FEATURE" ] || die "La branche FEATURE n'a pas été définie" + branch="${1#$FEATURE}" + [ -n "$branch" ] || die "Vous devez spécifier le nom de la branche" + branch="$FEATURE$branch" + + if ! array_contains LocalBranches "$branch"; then + array_contains AllBranches "$branch" && exit_with enote "\ +$branch: une branche du même nom existe dans l'origine + git checkout $branch" + _ensure_develop_branch + + resolve_should_push + + enote "Vous allez créer la branche ${COULEUR_VERTE}$branch${COULEUR_NORMALE} <-- ${COULEUR_BLEUE}$DEVELOP${COULEUR_NORMALE}" + ask_yesno "Voulez-vous continuer?" O || die + + einfo "Création de la branche $branch" + git checkout -b "$branch" "$DEVELOP" || die + push_branches+=("$branch") + + _push_branches + fi + git checkout -q "$branch" +} + +function init_action() { + local what="${1:-develop}"; shift + case "$what" in + init|repo|r) init_repo_action "$@";; + config) init_config_action "$@";; + composer) init_composer_action "$@";; + main|m) checkout_main_action;; + develop|dev|d) init_develop_action "$@";; + upstream|up|u) init_upstream_action "$@";; + dist|x) init_dist_action "$@";; + *) init_feature_action "$what" "$@";; + esac +} + +################################################################################ +# Programme principal +################################################################################ + +chdir= +ConfigBranch= +ConfigFile= +action=init +Origin= +[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push= +ForceCreate= +args=( + "gérer un projet git" + "\ +repo|config|composer +develop|upstream|dist + +INITIALISATION + +Par défaut, le script agit en mode initialisation qui permet de créer et/ou +configurer certaines branches du dépôt si elles n'existent pas déjà + + repo + initialiser un dépôt vide et créer les branches $MAIN et $DEVELOP + + develop + créer la branche $DEVELOP + upstream + créer la branche ${UPSTREAM:-UPSTREAM} en tant que source de la branche $DEVELOP + dist + créer la branche ${DIST:-DIST} en tant que destination de la branche $MAIN + anything + créer la branche ${FEATURE}anything à partir de la branche $DEVELOP" + -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" + -B:,--config-branch ConfigBranch= "++\ +branche à partir de laquelle charger la configuration" + -c:,--config-file:CONFIG ConfigFile= "++\ +fichier de configuration des branches. cette option est prioritaire sur --config-branch +par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" + -w,--show-config action=show "++\ +afficher la configuration chargée" + --composer-select-profile action=composer_select_profile "\ +sélectionner le profil composer spécifié en argument" + -O:,--origin Origin= "++\ +origine vers laquelle pousser les branches" + -n,--no-push Push= "\ +ne pas pousser les branches vers leur origine après leur création" + --push Push=1 "++\ +pousser les branches vers leur origine après leur création. +c'est l'option par défaut" + -f,--force-create ForceCreate=1 "\ +Avec config, forcer la (re)création du fichier .pman.conf" +) +parse_args "$@"; set -- "${args[@]}" + +# charger la configuration +ensure_gitdir "$chdir" +load_branches all +load_config "$MYNAME" +load_branches current + +# puis faire l'action que l'on nous demande +case "$action" in +show) + show_action "$@" + ;; +init) + git_ensure_cleancheckout + init_action "$@" + ;; +composer_select_profile) + exec "$MYDIR/_pman-$action.php" "$@" + ;; +*) + die "$action: action non implémentée" + ;; +esac diff --git a/wip/pmer b/wip/pmer new file mode 100755 index 0000000..9a7daf8 --- /dev/null +++ b/wip/pmer @@ -0,0 +1,262 @@ +#!/bin/bash +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +source "$(dirname -- "$0")/../load.sh" || exit 1 +require: git pman pman.conf + +git_cleancheckout_DIRTY="\ +Vous avez des modifications locales. +Enregistrez ces modifications avant de fusionner la branche" + +function show_action() { + local commits + setx commits=_list_commits + if [ -n "$commits" ]; then + if [ $ShowLevel -ge 2 ]; then + { + echo "\ +# Commits à fusionner $SrcBranch --> $DestBranch + +$commits +" + _sd_COLOR=always _show_diff + } | less -eRF + else + einfo "Commits à fusionner $SrcBranch --> $DestBranch" + eecho "$commits" + fi + fi +} + +function ensure_branches() { + [ -n "$SrcBranch" -a -n "$DestBranch" ] || + die "$SrcBranch: Aucune configuration de fusion trouvée pour cette branche" + + array_contains LocalBranches "$SrcBranch" || die "$SrcBranch: branche source introuvable" + array_contains LocalBranches "$DestBranch" || die "$DestBranch: branche destination introuvable" +} + +function merge_action() { + [ -z "$ShouldPush" ] && enote "\ +L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine" + + enote "\ +Ce script va +- fusionner la branche ${COULEUR_BLEUE}$SrcBranch${COULEUR_NORMALE} dans ${COULEUR_ROUGE}$DestBranch${COULEUR_NORMALE}${Push:+ +- pousser les branches modifiées}" + ask_yesno "Voulez-vous continuer?" O || die + + local script=".git/pman-merge.sh" + local -a push_branches delete_branches + local hook + local comment= + local or_die=" || exit 1" + + _mscript_start + _scripta < + AFTER_MERGE_ + AFTER_DELETE_ + BEFORE_PUSH_ + AFTER_PUSH_ +srcType et destType pouvant valoir UPSTREAM, DEVELOP, FEATURE, RELEASE, MAIN, HOTFIX, DIST" + -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" + -O:,--origin Origin= "++\ +origine à partir de laquelle les branches distantes sont considérées" + -B:,--config-branch ConfigBranch= "++\ +branche à partir de laquelle charger la configuration" + -c:,--config-file:CONFIG ConfigFile= "++\ +fichier de configuration des branches. cette option est prioritaire sur --config-branch +par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" + --fake _Fake=1 "++option non documentée" + --keep-script _KeepScript=1 "++option non documentée" + -w,--show '$action=show; inc@ ShowLevel' "\ +lister les modifications qui seraient fusionnées dans la branche destination" + -b,--rebase action=rebase "\ +lancer git rebase -i sur la branche source. cela permet de réordonner les +commits pour nettoyer l'historique avant la fusion" + --merge action=merge "++\ +fusionner la branche source dans la branche destination correspondante. +c'est l'action par défaut" + --tech-merge TechMerge=1 "++option non documentée" + -s:,--squash:COMMIT_MSG SquashMsg= "\ +fusionner les modifications de la branche comme un seul commit. +cette option ne devrait pas être utilisée avec --no-delete" + -n,--no-push Push= "\ +ne pas pousser les branches vers leur origine après la fusion" + --push Push=1 "++\ +pousser les branches vers leur origine après la fusion. +c'est l'option par défaut" + -k,--no-delete Delete= "\ +ne pas supprimer la branche après la fusion dans la destination" + --delete Delete=1 "++\ +supprimer la branche après la fusion dans la destination. +c'est l'option par défaut" + -f,--force-merge ForceMerge=1 "++\ +forcer la fusion pour une branche qui devrait être traitée par prel" + -a:,--after-merge AfterMerge= "\ +évaluer le script spécifié après une fusion *réussie*" +) +parse_args "$@"; set -- "${args[@]}" + +# charger la configuration +ensure_gitdir "$chdir" +load_branches all +load_config "$MYNAME" +load_branches current "$1" + +resolve_should_push quiet + +# puis faire l'action que l'on nous demande +case "$action" in +show) + git_check_cleancheckout || ewarn "$git_cleancheckout_DIRTY" + ensure_branches + show_action "$@" + ;; +merge) + ShouldDelete=1 + no_merge_msg="$SrcBranch: cette branche doit être fusionnée dans $DestBranch avec prel" + if [ "$SrcType" == develop ]; then + [ -z "$ForceMerge" ] && die "$no_merge_msg" + [ -n "$AfterMerge" ] || setx AfterMerge=qvals git checkout -q "$SrcBranch" + elif [ "$SrcType" == release -o "$SrcType" == hotfix ]; then + die "$no_merge_msg" + fi + # n'autoriser la suppression que pour feature + [ "$SrcType" == feature ] || ShouldDelete= + [ -z "$ShouldDelete" ] && Delete= + [ -z "$_Fake" ] && git_ensure_cleancheckout + if array_contains LocalBranches "$SrcBranch"; then + ensure_branches + merge_action "$@" + elif array_contains AllBranches "$SrcBranch"; then + enote "$SrcBranch: une branche du même nom existe dans l'origine" + die "$SrcBranch: branche locale introuvable" + else + die "$SrcBranch: branche introuvable" + fi + ;; +*) + die "$action: action non implémentée" + ;; +esac diff --git a/wip/prel b/wip/prel new file mode 100755 index 0000000..2ec3a31 --- /dev/null +++ b/wip/prel @@ -0,0 +1,292 @@ +#!/bin/bash +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +source "$(dirname -- "$0")/../load.sh" || exit 1 +require: git pman pman.conf + +git_cleancheckout_DIRTY="\ +Vous avez des modifications locales. +Enregistrez ces modifications avant de créer une release" + +function show_action() { + local commits + setx commits=_list_commits + if [ -n "$commits" ]; then + if [ $ShowLevel -ge 2 ]; then + { + echo "\ +# Commits à fusionner $SrcBranch --> $DestBranch + +$commits +" + _sd_COLOR=always _show_diff + } | less -eRF + else + einfo "Commits à fusionner $SrcBranch --> $DestBranch" + eecho "$commits" + fi + fi +} + +function ensure_branches() { + [ -n "$SrcBranch" -a -n "$DestBranch" ] || + die "$SrcBranch: Aucune configuration de fusion trouvée pour cette branche" + + array_contains LocalBranches "$SrcBranch" || die "$SrcBranch: branche source introuvable" + array_contains LocalBranches "$DestBranch" || die "$DestBranch: branche destination introuvable" + + Tag="$TAG_PREFIX$Version$TAG_SUFFIX" + local -a tags + setx -a tags=git tag -l "${TAG_PREFIX}*${TAG_SUFFIX}" + if [ -z "$ForceCreate" ]; then + array_contains tags "$Tag" && die "$Tag: le tag correspondant à la version existe déjà" + fi +} + +function create_release_action() { + if [ -n "$ReleaseBranch" ]; then + Version="${ReleaseBranch#$RELEASE}" + Tag="$TAG_PREFIX$Version$TAG_SUFFIX" + merge_release_action "$@"; return $? + elif [ -n "$HotfixBranch" ]; then + Version="${HotfixBranch#$HOTFIX}" + Tag="$TAG_PREFIX$Version$TAG_SUFFIX" + merge_hotfix_action "$@"; return $? + fi + + [ -n "$ManualRelease" ] && ewarn "\ +L'option --no-merge a été forcée puisque ce dépôt ne supporte pas les releases automatiques" + [ -z "$ShouldPush" ] && enote "\ +L'option --no-push a été forcée puisque ce dépôt n'a pas d'origine" + + if [ -z "$Version" -a -n "$CurrentVersion" -a -f VERSION.txt ]; then + Version="$(" + -d:,--chdir:BASEDIR chdir= "répertoire dans lequel se placer avant de lancer les opérations" + -O:,--origin Origin= "++\ +origine à partir de laquelle les branches distantes sont considérées" + -B:,--config-branch ConfigBranch= "++\ +branche à partir de laquelle charger la configuration" + -c:,--config-file:CONFIG ConfigFile= "++\ +fichier de configuration des branches. cette option est prioritaire sur --config-branch +par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe" + -n,--no-push Push= "\ +ne pas pousser les branches vers leur origine après la fusion" + --push Push=1 "++\ +pousser les branches vers leur origine après la fusion. +c'est l'option par défaut" +) +parse_args "$@"; set -- "${args[@]}" + +# charger la configuration +ensure_gitdir "$chdir" +load_branches all +load_config "$MYNAME" +load_branches current + +branch="$1" +if [ -z "$branch" -a ${#FeatureBranches[*]} -eq 1 ]; then + branch="${FeatureBranches[0]}" +fi +[ -n "$branch" ] || die "Vous devez spécifier la branche à créer" +branch="$FEATURE${branch#$FEATURE}" + +resolve_should_push +git_ensure_cleancheckout + +if array_contains AllBranches "$branch"; then + git checkout -q "$branch" +else + # si la branche source n'existe pas, la créer + args=(--origin "$Origin") + if [ -n "$ConfigFile" ]; then args+=(--config-file "$ConfigFile") + elif [ -n "$ConfigBranch" ]; then args+=(--config-branch "$ConfigBranch") + fi + [ -z "$Push" ] && args+=(--no-push) + exec "$MYDIR/pman" "${args[@]}" "$branch" +fi