diff --git a/.udir b/.udir index a5c7d43..b8ace89 100644 --- a/.udir +++ b/.udir @@ -18,7 +18,7 @@ kvm_service= openvz_service= configure_variables=(dest uninst_utools rm_utools kvm_service openvz_service) -configure_dest_for=(bashrc profile lib/uinst/conf lib/uinst/rootconf lib/profile.d/nutools lib/bashrc.d/bash_completion.nutools lib/init.d/kvm-stop-all legacy/sysinc/utools legacy/sysinc/system_caps legacy/sysinc/private/init) +configure_dest_for=(bashrc profile lib/uinst/conf lib/uinst/rootconf lib/profile.d/nutools lib/bashrc.d/bash_completion lib/init.d/kvm-stop-all legacy/sysinc/utools legacy/sysinc/system_caps legacy/sysinc/private/init) config_scripts=(lib/uinst/conf lib/uinst/system_caps.legacy) install_profiles=true profiledir=lib/profile.d diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000..fa64818 --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,91 @@ +## Version 1.0.0 du 14/04/2015-10:05 + +commencer à suivre les versions de nutools: cette release est la première de +la série + +66bbf23 Intégration de la branche update-ulibver +f5aeff7 maj de ulib +073e7b0 Intégration de la branche ptools +8f6a32b forcer la création de la destination. afficher un message informatif +48d9104 Intégration de la branche ptools +6890d30 workaround pour le bug sous debian squeeze +91de409 Intégration de la branche ptools +cd50646 ne pas mettre à jour le fichier local +f321f1c Intégration de la branche ptools +6258a6b utiliser la version au lieu de la release +5589314 bug +10a7d4e Intégration de la branche ptools +cd92832 ne pas supprimer la branche develop +3f1dc3e Intégration de la branche ptools +ce050db ajout d'un changelog possibilité d'éditer le changelog avec -e supprimer les options courtes -z et -Z +2bc314c ajout de --merge-log supprimer les options courtes -z et -Z +fc35a05 inclure la liste des modifications dans le log +4578219 Intégration de la branche ptools +5b0715e vérifier la présence dans le dépôt distant +0e6e94c Intégration de la feature branch ptools +10152b4 calcul de newver action delete +6c8e750 implémener -z et -Z +2f41de3 cosmetic +5f6d5bb ajout des options courtes -z et -Z +18bb510 supprimer l'option courte -d qui est déjà utilisée pour diff +dd2a712 ajout de -d et --force-delete +38f04ff maj doc +523d3f1 doc pour nouvelle fonctionnalité à implémenter +13dfb9a Intégration de la feature branch prel-tag +da96f72 ajout d'un tag après fusion de la branche dans master +2a71a51 Intégration de la feature branch prel-tag +09c59d8 ne pas afficher les erreurs +3e514d5 maj doc +f9d4556 Intégration de la feature branch linedots +7ae9b48 ajout de elinedots +ffa9195 fast-forwarder si possible +f64117c cosmetic +d8a3ed4 checkout par défaut +89be42e ne pas utiliser csort +881bcde tenir compte de la valeur de origin +7c67a7f tenir compte des branches potentielles +b757ca1 Intégration de la feature branch git-opts +c3683a5 bug +743e17b fast-forwarder automatiquement la branche vers laquelle on bascule +e3e3bbb ajout de git_fast_forward +1661ee5 ajout des fonctions git_is_ancestor(), git_should_ff(), git_should_push(), git_is_merged() +2e215cc utiliser l'api +b975724 maj doc +262d12e toujours charger le module +8ae0a8d utiliser nouvelle API --add-metadata +259e1be ajout de --add-metadata support de --allow-empty pour --update +8d3ab79 ajout de semver_addmetadata utiliser API moderne pour les perfs +ac940b8 ne garder que les infos sur la branche courante dans les metadata +1e11a57 ajouter pz pour faire une archive d'un projet +9389fb0 autoriser --allow-emptyp pour l'action --show +f90ad4d bug +26aa98f cosmetic +8deda74 cosmetic +f8c4a54 calcul de la version avec --prel +22a26d9 support des numéros style maven +4f0a746 support des fichiers pom.xml +6d85330 Intégration de la feature branch ptools +f60787a prel est maintenant en topevel +7647d2d prel est prêt à passer en toplevel +7c36761 possibilité de faire -u et -m dans la même commande +de618ae possibilité de ne pas supprimer une feature branch après son intégration +57bf621 cosmetic +8d4d35d mettre à jour la version avec pver +f98c977 support de -v en mode auto +4b64305 finaliser l'option -u +5862e75 ne pas charger le fichier s'il n'existe pas +e5b8b81 début d'implémentation de update +9235ce1 nettoyage +ffaed8a quelques corrections +9182dcf maj api chargement depuis ~/etc/completion.d +bbbc35a maj api chargement depuis ~/etc/completion.d +d2133c7 intégrer les modifications faites à l'ur +90772f0 Intégration de la feature branch completion +163df88 bug +e8d683b bug +041a830 suite du support de bash_completion +9c17a60 framework pour la complétion automatique +bbbe6c4 l'option -c ne fait que le basculement ou la création. Le choix de la version se fera avec -u +c5ba03b ajouter les completions pour prel +2b2b7f5 début d'implémentation de prel -c +3f925ca déplacer le code de pver dans ptools diff --git a/VERSION.txt b/VERSION.txt new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/VERSION.txt @@ -0,0 +1 @@ +1.0.0 diff --git a/lib/bashrc.d/bash_completion b/lib/bashrc.d/bash_completion new file mode 100644 index 0000000..7ee52d1 --- /dev/null +++ b/lib/bashrc.d/bash_completion @@ -0,0 +1,33 @@ +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +##@before * + +if [ -n "$UTOOLS_BASH_COMPLETION" ]; then + function __bash_completion_enabled() { return 1; } + function __bash_completion_module_enabled() { return 1; } + if [ -f /etc/debian_version ]; then + case "$("$bcdir/pdev" +./prel --nutools-completion >"$bcdir/prel" +#./pfix --nutools-completion >"$bcdir/pfix" + # copier le fichier .nutoolsrc [ -f ~/.nutoolsrc ] || cp lib/nutoolsrc ~/.nutoolsrc diff --git a/lib/ulib/.ulibver b/lib/ulib/.ulibver index aaa06e4..469f5f8 100644 --- a/lib/ulib/.ulibver +++ b/lib/ulib/.ulibver @@ -1 +1 @@ -007023000 +008000000 diff --git a/lib/ulib/base b/lib/ulib/base index 6edfd17..40c523d 100644 --- a/lib/ulib/base +++ b/lib/ulib/base @@ -3352,6 +3352,34 @@ function eend() { __tlevel="${__tlevel% }" fi } +function __elinedots() { + ebegin "$1" + local line + if show_debug; then + while read line; do + __edoto 1>&2 + __edotd "$line" 1>&2 + done + else + while read line; do + __edoto 1>&2 + done + fi + eend +} +function elinedots() { +# Afficher un message comme avec ebegin "$1", puis afficher un point '.' pour +# chaque ligne lue sur stdin. Cela permet de suivre une opération. En mode +# DEBUG, afficher la ligne affichée plutôt qu'un point. +# Si $2..$* sont spécifiés, lancer la commande et suivre sa sortie. Ainsi, +# 'elinedots msg cmd args' est un raccourci pour 'cmd args | elinedots msg' + local msg="$1"; shift + if [ $# -gt 0 ]; then + "$@" | __elinedots "$msg" + else + __elinedots "$msg" + fi +} function ask_yesno() { # Afficher le message $1 suivi de [oN] ou [On] suivant que $2 vaut O ou N, puis # lire la réponse. Retourner 0 si la réponse est vrai, 1 sinon. diff --git a/lib/ulib/bash_completion b/lib/ulib/bash40/bash_completion similarity index 98% rename from lib/ulib/bash_completion rename to lib/ulib/bash40/bash_completion index 8ea7b15..271e2da 100644 --- a/lib/ulib/bash_completion +++ b/lib/ulib/bash40/bash_completion @@ -1,12 +1,21 @@ ##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 -## Fonctions pour l'autocomplétion bash, si le package bash-completion n'est pas installé -## Attention! Ces fonctions ne sont testées que sur Debian Squeeze. Ce module -## est incompatible avec bash_completion sur Debian Wheezy. +## Fonctions pour l'autocomplétion bash, si le package bash-completion n'est pas +## installé. ATTENTION! Ces fonctions ont été pour la plupart récupérées de +## l'implémentation sous Debian Squeeze, ce qui signifie qu'elles sont conçues +## pour fonctionner avec bash 4.0 ##@cooked nocomments -##@require base +## ATTENTION! Ce module ne doit pas avoir de dépendances externes parce qu'il +## doit pouvoir être chargé depuis ~/etc/bashrc.d uprovide bash_completion -if [ -z "$BASH_COMPLETION" ]; then +function __bash_completion_enabled() { + [ -n "$BASH_COMPLETION" ] +} +function __bash_completion_module_enabled() { + [ -n "$BASH_COMPLETION_DIR" -a -f "$BASH_COMPLETION_DIR/$1" ] +} + +if ! __bash_completion_enabled; then BASH_COMPLETION=1 shopt -s extglob progcomp diff --git a/lib/ulib/bash41/bash_completion b/lib/ulib/bash41/bash_completion new file mode 100644 index 0000000..a21de3f --- /dev/null +++ b/lib/ulib/bash41/bash_completion @@ -0,0 +1,35 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Fonctions pour l'autocomplétion bash, si le package bash-completion n'est pas +## installé. ATTENTION! Ces fonctions ont été pour la plupart récupérées de +## l'implémentation sous Debian Wheezy, ce qui signifie qu'elles sont conçues +## pour fonctionner avec bash 4.1 +##@cooked nocomments +## ATTENTION! Ce module ne doit pas avoir de dépendances externes parce qu'il +## doit pouvoir être chargé depuis ~/etc/bashrc.d +uprovide bash_completion + +function __bash_completion_enabled() { + [ -n "$__NUTOOLS_BASH_COMPLETION" ] && return 0 + grep -qE '^[ \t]*(\.|source)[ \t]*/usr/share/bash-completion/bash_completion' /etc/bash.bashrc && return 0 + grep -qE '^[ \t]*(\.|source)[ \t]*/usr/share/bash-completion/bash_completion' ~/.bashrc && return 0 + return 1 +} +function __bash_completion_module_enabled() { + if [ -f "/usr/share/bash-completion/completions/$1" ]; then + local var="__NUTOOLS_BASH_COMPLETION_${1//-/_}" + if [ -z "${!var}" ]; then + # nous ne supportons pas le chargement à la demande: charger le + # module de suite + source "/usr/share/bash-completion/completions/$1" + eval "$var=1" + fi + return 0 + fi + [ -n "$BASH_COMPLETION_COMPAT_DIR" -a -f "$BASH_COMPLETION_COMPAT_DIR/$1" ] && return 0 + return 1 +} + +if ! __bash_completion_enabled; then + __NUTOOLS_BASH_COMPLETION=1 +fi +[ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=1 diff --git a/lib/ulib/ptools b/lib/ulib/ptools index b8f286a..d1f62fb 100644 --- a/lib/ulib/ptools +++ b/lib/ulib/ptools @@ -6,47 +6,564 @@ uprovide ptools urequire vcs semver -function __get_branch() { - local branch="$1" - [ -n "$branch" ] || branch="$(git_get_branch)" - echo "$branch" -} - -function is_master_branch() { - local branch; branch="$(__get_branch "$1")" || return 2 - [ "$branch" == "master" ] -} -function is_develop_branch() { - local branch; branch="$(__get_branch "$1")" || return 2 - [ "$branch" == "develop" ] -} -function is_release_branch() { - local branch; branch="$(__get_branch "$1")" || return 2 - [[ "$branch" == release-* ]] -} -function is_hotfix_branch() { - local branch; branch="$(__get_branch "$1")" || return 2 - [[ "$branch" == hotfix-* ]] -} -function is_feature_branch() { - local branch; branch="$(__get_branch "$1")" || return 2 - [ "$branch" == "master" ] && return 1 - [ "$branch" == "develop" ] && return 1 - [[ "$branch" == release-* ]] && return 1 - [[ "$branch" == hotfix-* ]] && return 1 - return 0 +function is_any_branch() { + local branch="$1"; shift + if [ -z "$branch" ]; then + branch="$(git_get_branch)" || return 2 + fi + local spec r + for spec in "$@"; do + case "$spec" in + m|master) + [ -n "$r" ] || r=1 + [ "$branch" == "master" ] && return 0 + ;; + d|develop) + [ -n "$r" ] || r=1 + [ "$branch" == "develop" ] && return 0 + ;; + r|release) + [ -n "$r" ] || r=1 + [[ "$branch" == release-* ]] && return 0 + ;; + h|hotfix) + [ -n "$r" ] || r=1 + [[ "$branch" == hotfix-* ]] && return 0 + ;; + f|feature|t|topic) + [ -n "$r" ] || r=1 + [ "$branch" == "master" ] && continue + [ "$branch" == "develop" ] && continue + [[ "$branch" == release-* ]] && continue + [[ "$branch" == hotfix-* ]] && continue + return 0 + ;; + -m|-master) + [ -n "$r" ] || r=0 + [ "$branch" == "master" ] && return 1;; + -d|-develop) + [ -n "$r" ] || r=0 + [ "$branch" == "develop" ] && return 1;; + -r|-release) + [ -n "$r" ] || r=0 + [[ "$branch" == release-* ]] && return 1;; + -h|-hotfix) + [ -n "$r" ] || r=0 + [[ "$branch" == hotfix-* ]] && return 1;; + -f|-feature|-t|-topic) + [ -n "$r" ] || r=0 + [ "$branch" == "master" ] && continue + [ "$branch" == "develop" ] && continue + [[ "$branch" == release-* ]] && continue + [[ "$branch" == hotfix-* ]] && continue + return 1 + ;; + esac + done + return ${r:-1} } +function is_master_branch() { is_any_branch "$1" master; } +function is_develop_branch() { is_any_branch "$1" develop; } +function is_release_branch() { is_any_branch "$1" release; } +function is_hotfix_branch() { is_any_branch "$1" hotfix; } +function is_feature_branch() { is_any_branch "$1" feature; } function list_release_branches() { - git_list_branches | grep '^release-' + local origin="$1" + git_list_${origin:+p}branches "$origin" | grep '^release-' } function list_hotfix_branches() { - git_list_branches | grep '^hotfix-' + local origin="$1" + git_list_${origin:+p}branches "$origin" | grep '^hotfix-' } function list_feature_branches() { - git_list_branches | + local origin="$1" + git_list_${origin:+p}branches "$origin" | grep -vF master | grep -vF develop | grep -v '^release-' | grep -v '^hotfix-' } + +################################################################################ +# Outils de haut niveau + +function __pom_get_version() { + # obtenir la version dans le pom $1(=pom.xml) + local pom="${1:-pom.xml}" + awk <"$pom" '/^[ \t]*/ { + sub(/^.*/, "") + sub(/<\/version>.*$/, "") + print + exit +}' +} +function __pom_set_version() { + # modifier la version du le fichier $1(=pom.xml) à la valeur + # $2(=1.0.0-SNAPSHOT) + local pom="${1:-pom.xml}" + local version="${2:-1.0.0-SNAPSHOT}" + local tmpfile; ac_set_tmpfile tmpfile + awk <"$pom" >"$tmpfile" ' +BEGIN { + version = '"$(qawk "$version")"' + found = 0 +} +!found && $0 ~ /^[ \t]*/ { + prefix = "" + if (match($0, /^.*/)) { + prefix = substr($0, RSTART, RLENGTH) + } + suffix = "" + if (match($0, /<\/version>.*$/)) { + suffix = substr($0, RSTART, RLENGTH) + } + print prefix version suffix + found = 1 + next +} +{ print }' + cat "$tmpfile" >"$pom" + ac_clean "$tmpfile" +} + +function pver() { + local DEFAULT_FILE=VERSION.txt + local DEFAULT_POM=pom.xml + + local -a args + local action=auto + local source=auto + local file= + local git= + local version= + local allow_empty= + local convert=auto + local operator= + local oversion= + local setversion= + local incversion= + local setprelease= + local setalpha= + local setbeta= + local setrc= + local setrelease= + local setmetadata= addmetadata= + local vcsmetadata= + parse_opts "${PRETTYOPTS[@]}" \ + --help '$exit_with pver_display_help' \ + -f:,--file: '$set@ file; source=file' \ + -e:,--maven:,--pom: '$set@ file; source=pom' \ + -F:,--file-string: '$set@ file; source=file-string' \ + -g:,--git-string: '$set@ git; source=git-string' \ + -s:,--string: '$set@ version; source=string' \ + --show action=show \ + --allow-empty allow_empty=1 \ + --check action=check \ + --convert convert=1 \ + --no-convert convert= \ + --eq: '$action=compare; operator=eq; set@ oversion' \ + --ne: '$action=compare; operator=ne; set@ oversion' \ + --lt: '$action=compare; operator=lt; set@ oversion' \ + --le: '$action=compare; operator=le; set@ oversion' \ + --gt: '$action=compare; operator=gt; set@ oversion' \ + --ge: '$action=compare; operator=ge; set@ oversion' \ + -v:,--set-version: '$action=update; set@ setversion; incversion=' \ + --prel '$action=update; setversion=prel; incversion=' \ + -u,--update '$action=update; [ -z "$incversion" ] && incversion=auto' \ + --menu '$action=update; incversion=menu' \ + -x,--major '$action=update; incversion=major' \ + -z,--minor '$action=update; incversion=minor' \ + -p,--patchlevel '$action=update; incversion=patchlevel' \ + -l:,--prelease:,--prerelease: '$action=update; set@ setprelease; [ -z "$setprelease" ] && { setalpha=; setbeta=; setrc=; setrelease=1; }' \ + -a,--alpha '$action=update; setalpha=1; setbeta=; setrc=; setrelease=' \ + -b,--beta '$action=update; setalpha=; setbeta=1; setrc=; setrelease=' \ + -r,--rc '$action=update; setalpha=; setbeta=; setrc=1; setrelease=' \ + -R,--release,--final '$action=update; setalpha=; setbeta=; setrc=; setrelease=1' \ + -m:,--metadata:,--set-metadata: '$action=update; set@ setmetadata' \ + --add-metadata: '$action=update; set@ addmetadata' \ + -M,--vcs-metadata '$action=update; vcsmetadata=1' \ + @ args -- "$@" && set -- "${args[@]}" || { eerror "$args"; return 1; } + + # Calculer la source + if [ "$source" == auto ]; then + source=file + for i in "$DEFAULT_FILE" version.txt "$DEFAULT_POM"; do + if [ -f "$i" ]; then + case "$i" in + "$DEFAULT_POM") + source=pom + file="$i" + break + ;; + *) + source=file + file="$i" + break + ;; + esac + fi + done + elif [ "$source" == file ]; then + [ "$action" == auto ] && action=update + fi + [ "$source" == file -a -z "$file" ] && file="$DEFAULT_FILE" + [ "$source" == pom -a -z "$file" ] && file="$DEFAULT_POM" + [ "$action" == auto ] && action=show + + # Lire la version + if [ "$source" == file ]; then + [ -f "$file" ] && version="$(<"$file")" + elif [ "$source" == pom ]; then + [ -f "$file" ] || { + eerror "$file: fichier introuvable" + return 1 + } + version="$(__pom_get_version "$file")" + elif [ "$source" == file-string ]; then + if [ -z "$file" ]; then + file="$DEFAULT_FILE" + elif [ -d "$file" ]; then + file="$file/$DEFAULT_FILE" + fi + [ -f "$file" ] && version="$(<"$file")" + file= + elif [ "$source" == git-string ]; then + splitfsep2 "$git" : branch name + [ -n "$branch" ] || branch=master + [ -n "$name" ] || name="$DEFAULT_FILE" + if git rev-parse --verify --quiet "$branch:$name" >/dev/null; then + version="$(git cat-file blob "$branch:$name" 2>/dev/null)" + fi + fi + [ -n "$version" -o -n "$allow_empty" ] || version=0.0.0 + + # Conversion éventuelle du numéro de version + psemver_parse "$version" + [ -n "$valid" ] && convert= + if [ "$convert" == auto ]; then + [ -z "$valid" ] && convert=1 + fi + if [ -n "$convert" -a -n "$version" ]; then + mversion="$(awkrun version="$version" ' +function nbdot(s) { + gsub(/[^.]/, "", s) + return length(s) +} +BEGIN { + ### utools, legacy + if (version ~ /[0-9]+(\.[0-9]+)*(-r[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9][0-9][0-9])?$/) { + metadata = "" + # traiter release date + pos = length(version) - 12 + if (pos > 0) { + rdate = substr(version, pos + 3) + metadata = substr(rdate, 7, 4) substr(rdate, 4, 2) substr(rdate, 1, 2) + version = substr(version, 1, pos) + } + # traiter metadata + match(version, /[0-9]+(\.[0-9]+(\.[0-9]+)?)?/) + pos = RLENGTH + if (pos < length(version)) { + if (metadata != "") metadata = metadata "." + metadata = metadata substr(version, pos + 2) + } + version = substr(version, 1, pos) + # ajouter les éléments manquants + while (nbdot(version) < 2) { + version = version ".0" + } + # afficher la version migrée au format semver + if (metadata != "") print version "+" metadata + else print version + + ### maven, pom.xml + } else if (version ~ /[0-9]+(\.[0-9]+)*(-[sS][nN][aA][pP][sS][hH][oO][tT])?$/) { + + prerelease = "" + # traiter prerelease + pos = length(version) - 9 + if (pos > 0) { + prerelease = substr(version, pos + 2) + version = substr(version, 1, pos) + } + # traiter prerelease + match(version, /[0-9]+(\.[0-9]+(\.[0-9]+)?)?/) + pos = RLENGTH + if (pos < length(version)) { + if (prerelease != "") prerelease = prerelease "." + prerelease = prerelease substr(version, pos + 2) + } + version = substr(version, 1, pos) + # ajouter les éléments manquants + while (nbdot(version) < 2) { + version = version ".0" + } + # afficher la version migrée au format semver + if (prerelease != "") print version "-" prerelease + else print version + } +}')" + if [ -n "$mversion" ]; then + version="$mversion" + psemver_parse "$version" + fi + fi + + # Actions + if [ "$action" == show ]; then + if [ -n "$version" ]; then + if isatty; then + estepi "La version actuelle est $version" + else + echo "$version" + fi + return 0 + else + if isatty; then + estepi "Il n'y a pas de version définie" + fi + return 1 + fi + fi + + if [ "$action" == check ]; then + [ -n "$valid" ] || { eerror "Numéro de version invalide: $version"; return 1; } + + elif [ "$action" == compare ]; then + psemver_parse "$oversion" o + + case "$operator" in + eq|same) + for var in valid major minor patchlevel; do + ovar="o$var" + [ "${!var}" == "${!ovar}" ] || return 1 + done + array_eq prelease oprelease || return 1 + if [ "$operator" == same ]; then + array_eq metadata ometadata || return 1 + fi + return 0 + ;; + ne|diff) + for var in valid major minor patchlevel; do + ovar="o$var" + [ "${!var}" != "${!ovar}" ] && return 0 + done + ! array_eq prelease oprelease && return 0 + if [ "$operator" == diff ]; then + ! array_eq metadata ometadata && return 0 + fi + return 1 + ;; + lt) + [ -z "$valid" -a -z "$ovalid" ] && return 1 + [ "$major" -lt "$omajor" ] && return 0 + [ "$major" -gt "$omajor" ] && return 1 + [ "$minor" -lt "$ominor" ] && return 0 + [ "$minor" -gt "$ominor" ] && return 1 + [ "$patchlevel" -lt "$opatchlevel" ] && return 0 + [ "$patchlevel" -gt "$opatchlevel" ] && return 1 + case "$(psemver_compare_prelease "" o)" in + lt) return 0;; + esac + return 1 + ;; + le) + [ -z "$valid" -a -z "$ovalid" ] && return 1 + [ "$major" -lt "$omajor" ] && return 0 + [ "$major" -gt "$omajor" ] && return 1 + [ "$minor" -lt "$ominor" ] && return 0 + [ "$minor" -gt "$ominor" ] && return 1 + [ "$patchlevel" -lt "$opatchlevel" ] && return 0 + [ "$patchlevel" -gt "$opatchlevel" ] && return 1 + case "$(psemver_compare_prelease "" o)" in + lt|eq) return 0;; + esac + return 1 + ;; + gt) + [ -z "$valid" -a -z "$ovalid" ] && return 1 + [ "$major" -lt "$omajor" ] && return 1 + [ "$major" -gt "$omajor" ] && return 0 + [ "$minor" -lt "$ominor" ] && return 1 + [ "$minor" -gt "$ominor" ] && return 0 + [ "$patchlevel" -lt "$opatchlevel" ] && return 1 + [ "$patchlevel" -gt "$opatchlevel" ] && return 0 + case "$(psemver_compare_prelease "" o)" in + gt) return 0;; + esac + return 1 + ;; + ge) + [ -z "$valid" -a -z "$ovalid" ] && return 1 + [ "$major" -lt "$omajor" ] && return 1 + [ "$major" -gt "$omajor" ] && return 0 + [ "$minor" -lt "$ominor" ] && return 1 + [ "$minor" -gt "$ominor" ] && return 0 + [ "$patchlevel" -lt "$opatchlevel" ] && return 1 + [ "$patchlevel" -gt "$opatchlevel" ] && return 0 + case "$(psemver_compare_prelease "" o)" in + gt|eq) return 0;; + esac + return 1 + ;; + esac + + elif [ "$action" == update ]; then + [ -z "$version" -a -n "$allow_empty" ] && return 1 + [ -n "$valid" ] || { eerror "Numéro de version invalide: $version"; return 1; } + + if [ -n "$file" ]; then + if [ -f "$file" ]; then + if isatty; then + estepi "La version actuelle est $version" + fi + elif [ "$source" == pom ]; then + eerror "$file: fichier introuvable" + return 1 + else + if isatty; then + ask_yesno "Le fichier $(ppath "$file") n'existe pas. Faut-il le créer?" O || return 1 + fi + fi + fi + + # forcer le numéro de version + if [ -n "$setversion" ]; then + if [ "$setversion" == prel ]; then + local branch; branch="$(git_get_branch)" || return 2 + if [[ "$branch" == release-* ]]; then + setversion="${branch#release-}" + else + eerror "$branch: n'est pas une release branch" + return 1 + fi + fi + psemver_setversion "$setversion" "" || { eerror "Numéro de version invalide: $setversion"; return 1; } + fi + + # Calculer metadata + if [ -n "$vcsmetadata" ]; then + setmetadata="$(git rev-parse --short HEAD)" || return 1 + fi + + # incrémenter les numéros de version + if [ "$incversion" == auto ]; then + if [ -n "$setrelease" -o -n "$setprelease" -o -n "$setmetadata" -o -n "$addmetadata" ]; then + incversion= + else + incversion=menu + fi + fi + if [ "$incversion" == menu ]; then + psemver_copy x; { + psemver_incmajor x + psemver_setprelease "$setprelease" x + if [ -n "$addmetadata" ]; then + [ -n "$setmetadata" ] && psemver_setmetadata "$setmetadata" x + psemver_addmetadata "$addmetadata" x + else + psemver_setmetadata "$setmetadata" x + fi + psemver_setvar versionx x + } + psemver_copy z; { + psemver_incminor z + psemver_setprelease "$setprelease" z + if [ -n "$addmetadata" ]; then + [ -n "$setmetadata" ] && psemver_setmetadata "$setmetadata" z + psemver_addmetadata "$addmetadata" z + else + psemver_setmetadata "$setmetadata" z + fi + psemver_setvar versionz z + } + psemver_copy p; { + psemver_incpatchlevel p + psemver_setprelease "$setprelease" p + if [ -n "$addmetadata" ]; then + [ -n "$setmetadata" ] && psemver_setmetadata "$setmetadata" p + psemver_addmetadata "$addmetadata" p + else + psemver_setmetadata "$setmetadata" p + fi + psemver_setvar versionp p + } + psemver_copy k; { + psemver_setprelease "$setprelease" k + if [ -n "$addmetadata" ]; then + [ -n "$setmetadata" ] && psemver_setmetadata "$setmetadata" k + psemver_addmetadata "$addmetadata" k + else + psemver_setmetadata "$setmetadata" k + fi + psemver_setvar versionk k + } + nextvs=( + "$versionx : maj incompatibles de l'API (-x)" + "$versionz : maj compatibles de l'API (-z)" + "$versionp : correction de bugs (-p)" + "$versionk : ne pas incrémenter la version" + ) + nextv="${nextvs[1]}" + simple_menu nextv nextvs \ + -t "Incrémenter le numéro de version" \ + -m "Veuillez choisir la prochaine version" + case "${nextv%)}" in + *-x) incversion=major;; + *-z) incversion=minor;; + *-p) incversion=patchlevel;; + *) incversion=;; + esac + fi + if [ -n "$incversion" ]; then + case "$incversion" in + major) psemver_incmajor;; + minor) psemver_incminor;; + patchlevel) psemver_incpatchlevel;; + esac + # Quand on incrémente, réinitialiser la valeur de prérelease et metadata + psemver_setprelease + [ -z "$addmetadata" ] && psemver_setmetadata + fi + + # spécifier prerelease + if [ -n "$setrelease" ]; then + psemver_setprelease "" + elif [ -n "$setprelease" ]; then + psemver_setprelease "$setprelease" || { eerror "Identifiant de pre-release invalide: $setprelease"; return 1; } + fi + if [ -n "$setalpha" ]; then + : #XXX + elif [ -n "$setbeta" ]; then + : #XXX + elif [ -n "$setrc" ]; then + : #XXX + fi + + # spécifier metadata + if [ -n "$setmetadata" ]; then + psemver_setmetadata "$setmetadata" || { eerror "Identifiant de build invalide: $setmetadata"; return 1; } + fi + if [ -n "$addmetadata" ]; then + psemver_addmetadata "$addmetadata" || { eerror "Identifiant de build invalide: $addmetadata"; return 1; } + fi + + # afficher le résultat final + psemver_setvar version + if [ -n "$file" ]; then + case "$source" in + file) echo "$version" >"$file";; + pom) __pom_set_version "$file" "$version";; + esac + fi + if isatty; then + estepn "La nouvelle version est $version" + else + echo "$version" + fi + fi + + return 0 +} diff --git a/lib/ulib/semver b/lib/ulib/semver index 5c96594..5b04956 100644 --- a/lib/ulib/semver +++ b/lib/ulib/semver @@ -14,12 +14,12 @@ function semver_parse() { local __p_ma="${2:-major}" __p_mi="${3:-minor}" __p_pl="${4:-patchlevel}" local __p_pr="${5:-prelease}" __p_md="${6:-metadata}" __p_va="${7:-valid}" local __p_tmp - set_var "$__p_ma" "" - set_var "$__p_mi" "" - set_var "$__p_pl" "" + setv "$__p_ma" "" + setv "$__p_mi" "" + setv "$__p_pl" "" array_new "$__p_pr" array_new "$__p_md" - set_var "$__p_va" "" + setv "$__p_va" "" # vérifier les caractères valides __semver_check_version "$__p_ver" || return 1 @@ -32,7 +32,7 @@ function semver_parse() { done [ "${__p_ver:0:1}" == . ] || return 1 __p_ver="${__p_ver:1}" - set_var "$__p_ma" "$__p_tmp" + setv "$__p_ma" "$__p_tmp" # extraire minor __p_tmp= @@ -42,7 +42,7 @@ function semver_parse() { done [ "${__p_ver:0:1}" == . ] || return 1 __p_ver="${__p_ver:1}" - set_var "$__p_mi" "$__p_tmp" + setv "$__p_mi" "$__p_tmp" # extraire patchlevel __p_tmp= @@ -51,7 +51,7 @@ function semver_parse() { __p_ver="${__p_ver:1}" done [ -z "$__p_ver" -o "${__p_ver:0:1}" == - -o "${__p_ver:0:1}" == + ] || return 1 - set_var "$__p_pl" "$__p_tmp" + setv "$__p_pl" "$__p_tmp" # extraire prelease if [ "${__p_ver:0:1}" == - ]; then @@ -79,25 +79,25 @@ function semver_parse() { # on doit avoir tout analysé [ -z "$__p_ver" ] || return 1 - set_var "$__p_va" 1 + setv "$__p_va" 1 return 0 } function semver_incmajor() { - set_var "$1" $((${!1} + 1)) - set_var "$2" 0 - set_var "$3" 0 + setv "$1" $((${!1} + 1)) + setv "$2" 0 + setv "$3" 0 array_new "$4" } function semver_incminor() { - set_var "$2" $((${!2} + 1)) - set_var "$3" 0 + setv "$2" $((${!2} + 1)) + setv "$3" 0 array_new "$4" } function semver_incpatchlevel() { - set_var "$3" $((${!3} + 1)) + setv "$3" $((${!3} + 1)) array_new "$4" } @@ -105,9 +105,9 @@ function semver_setversion() { local __sv_ma __sv_mi __sv_svl __sv_svr __sv_md __sv_va semver_parse "$1" __sv_ma __sv_mi __sv_pl __sv_pr __sv_md __sv_va [ -n "$__sv_va" ] || return 1 - set_var "$2" "$__sv_ma" - set_var "$3" "$__sv_mi" - set_var "$4" "$__sv_pl" + setv "$2" "$__sv_ma" + setv "$3" "$__sv_mi" + setv "$4" "$__sv_pl" return 0 } @@ -188,28 +188,38 @@ function semver_setmetadata() { return 0 } +function semver_addmetadata() { + if [ -n "$1" ]; then + __semver_check_metadata "$1" || return 1 + local -a __sam_metadata + array_split __sam_metadata "$1" . + array_extend "$6" __sam_metadata + fi + return 0 +} + function semver_compare_metadata() { # même algo que pour prelease semver_compare_prelease "$@" } function semver_copy() { - set_var "$1" "${!6}" - set_var "$2" "${!7}" - set_var "$3" "${!8}" + setv "$1" "${!6}" + setv "$2" "${!7}" + setv "$3" "${!8}" array_copy "$4" "$9" array_copy "$5" "${10}" } function semver_build() { echo_ "${!1}.${!2}.${!3}" - array_isempty "$4" || rawecho_ "-$(array_join "$4" .)" - array_isempty "$5" || rawecho_ "+$(array_join "$5" .)" + array_isempty "$4" || recho_ "-$(array_join "$4" .)" + array_isempty "$5" || recho_ "+$(array_join "$5" .)" echo "" } function semver_setvar() { - set_var "$1" "$(semver_build "$2" "$3" "$4" "$5" "$6")" + setv "$1" "$(semver_build "$2" "$3" "$4" "$5" "$6")" } ################################################################################ @@ -225,6 +235,7 @@ function psemver_setversion() { semver_setversion "$1" "${2}major" "${2}minor" " function psemver_setprelease() { semver_setprelease "$1" "${2}major" "${2}minor" "${2}patchlevel" "${2}prelease" "${2}metadata"; } function psemver_compare_prelease() { semver_compare_prelease "${1}prelease" "${2}prelease"; } function psemver_setmetadata() { semver_setmetadata "$1" "${2}major" "${2}minor" "${2}patchlevel" "${2}prelease" "${2}metadata"; } +function psemver_addmetadata() { semver_addmetadata "$1" "${2}major" "${2}minor" "${2}patchlevel" "${2}prelease" "${2}metadata"; } function psemver_compare_metadata() { semver_compare_metadata "${1}metadata" "${2}metadata"; } function psemver_copy() { semver_copy "${1}major" "${1}minor" "${1}patchlevel" "${1}prelease" "${1}metadata" "${2}major" "${2}minor" "${2}patchlevel" "${2}prelease" "${2}metadata"; } function psemver_build() { semver_build "${1}major" "${1}minor" "${1}patchlevel" "${1}prelease" "${1}metadata"; } diff --git a/lib/ulib/vcs b/lib/ulib/vcs index 1248feb..c09a66e 100644 --- a/lib/ulib/vcs +++ b/lib/ulib/vcs @@ -523,6 +523,8 @@ __VCS_GIT_ADVANCED_MAP=( gb:git_get_branch ib:git_is_branch hr:git_have_remote tb:git_track_branch cc:git_check_cleancheckout ec:git_ensure_cleancheckout + ia:git_is_ancestor sff:git_should_ff spu:git_should_push + im:git_is_merged ) __VCS_GIT_ADVANCED=( git_check_gitvcs git_ensure_gitvcs @@ -531,6 +533,8 @@ __VCS_GIT_ADVANCED=( git_get_branch git_is_branch git_have_remote git_track_branch git_check_cleancheckout git_ensure_cleancheckout + git_is_ancestor git_should_ff git_should_push + git_is_merged ) function git_check_gitvcs() { [ "$(_vcs_get_type "$(_vcs_get_dir)")" == git ] @@ -544,6 +548,16 @@ function git_list_branches() { function git_list_rbranches() { git for-each-ref "refs/remotes/${1:-origin}/" --format='%(refname:short)' | csort } +function git_list_pbranches() { + # lister les branches locales et celles qui existent dans l'origine + # $1(=origin) et qui pourraient devenir une branche locale avec la commande + # git checkout + local prefix="${1:-origin}/" + { + git for-each-ref refs/heads/ --format='%(refname:short)' + git for-each-ref "refs/remotes/$prefix" --format='%(refname:short)' | grep -F "$prefix" | cut -c $((${#prefix} + 1))- + } | grep -vF HEAD | csort -u +} function git_have_branch() { git_list_branches | grep -qF "$1" } @@ -596,6 +610,60 @@ function git_ensure_cleancheckout() { git_check_cleancheckout || die "Vous avez des modifications locales. Enregistrez ces modifications avant de continuer" } +function __git_init_ff() { + o="${3:-origin}" + b="$1" s="${2:-remotes/$o/$1}" + b="$(git rev-parse --verify --quiet "$b")" || return 1 + s="$(git rev-parse --verify --quiet "$s")" || return 1 + return 0 +} +function __git_can_ff() { + [ "$1" == "$(git merge-base "$1" "$2")" ] +} +function git_is_ancestor() { + # vérifier que la branche $1 est un ancêtre direct de la branche $2, qui + # vaut par défaut remotes/${3:-origin}/$1 + # note: cette fonction retourne vrai si $1 et $2 identifient le même commit + local o b s; __git_init_ff "$@" || return + __git_can_ff "$b" "$s" +} +function git_should_ff() { + # vérifier si la branche $1 devrait être fast-forwardée à partir de la + # branche d'origine $2, qui vaut par défaut remotes/${3:-origin}/$1 + # note: cette fonction est similaire à git_is_ancestor(), mais retourne + # false si $1 et $2 identifient le même commit + local o b s; __git_init_ff "$@" || return + [ "$b" != "$s" ] || return 1 + __git_can_ff "$b" "$o" +} +function git_should_push() { + # vérifier si la branche $1 devrait être poussée vers la branche de même nom + # dans l'origine $2(=origin), parce que l'origin peut-être fast-forwardée à + # partir de cette branche. + git_should_ff "remotes/${2:-origin}/$1" "$1" +} +function git_fast_forward() { + # vérifier que la branche courante est bien $1, puis tester s'il faut la + # fast-forwarder à partir de la branche d'origine $2, puis le faire si c'est + # nécessaire. la branche d'origine $2 vaut par défaut remotes/origin/$1 + local o b s; __git_init_ff "$@" || return + [ "$b" != "$s" ] || return 1 + local head="$(git rev-parse HEAD)" + [ "$head" == "$b" ] || return 1 + __git_can_ff "$b" "$s" || return 1 + git merge --ff-only "$s" +} + +function git_is_merged() { + # vérifier que les branches $1 et $2 ont un ancêtre commun, et que la + # branche $1 a été complètement fusionnée dans la branche destination $2 + local b="$1" d="$2" + b="$(git rev-parse --verify --quiet "$b")" || return 1 + d="$(git rev-parse --verify --quiet "$d")" || return 1 + [ -n "$(git merge-base "$b" "$d")" ] || return 1 + [ -z "$(git rev-list "$d..$b")" ] +} + # fonctions pour git annex function git_annex_initial() { # sur le dépôt $1 fraichement cloné, vérifier s'il faut faire git annex diff --git a/pdev b/pdev index e050b6b..63a2924 100755 --- a/pdev +++ b/pdev @@ -1,5 +1,18 @@ #!/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 __pdev_completion() { + local cur + _get_comp_words_by_ref cur + COMPREPLY=($(compgen -W "$(__pdev_branches)" "$cur")) +} +complete -F __pdev_completion pdev +' + exit 0 +fi + source "$(dirname "$0")/lib/ulib/ulib" || exit 1 urequire DEFAULTS ptools @@ -35,9 +48,23 @@ OPTIONS 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 + -m, --merge Si la branche actuelle est une feature branch, la merger dans develop puis la supprimer. Puis basculer sur la branche develop. + --merge-log + Ajouter un résumé des modifications sur la feature branch dans le + message du merge + -k, --keep + Avec l'option -m, ne pas supprimer une feature branch après l'avoir + fusionnée dans develop. + --delete + Supprimer une feature branch, à condition qu'elle aie déjà été + entièrement fusionnée dans la branch develop + --force-delete + Supprimer une feature branch, même si elle n'a pas encore été fusionnée + dans la branche develop + -l, --log -d, --diff Afficher les modifications entre deux branches. L'option --log affiche @@ -52,6 +79,9 @@ OPTIONS projdir= origin=origin action=branch +merge_log= +merge_delete=1 +force_delete= log= diff= parse_opts "${PRETTYOPTS[@]}" \ @@ -61,6 +91,10 @@ parse_opts "${PRETTYOPTS[@]}" \ -o,--offline UTOOLS_VCS_OFFLINE=1 \ --online UTOOLS_VCS_OFFLINE= \ -m,--merge action=merge \ + --merge-log merge_log=1 \ + -k,--keep merge_delete= \ + --delete action=delete \ + --force-delete '$action=delete; force_delete=1' \ -l,--log '$action=diff; log=1' \ -d,--diff '$action=diff; diff=1' \ @ args -- "$@" && set -- "${args[@]}" || die "$args" @@ -77,13 +111,12 @@ if ! git_have_branch develop; then fi setx branch=git_get_branch - if [ "$action" == branch ]; then feature="$1" source="${2:-develop}" if [ -z "$feature" ]; then - setx -a branches=list_feature_branches + setx -a branches=list_feature_branches "$origin" if [ ${#branches[*]} -eq 0 ]; then # En l'absence de feature branch, basculer sur develop @@ -103,13 +136,18 @@ if [ "$action" == branch ]; then if [ -z "$UTOOLS_VCS_OFFLINE" ]; then git_track_branch "$feature" "$origin" fi + git_fast_forward "$feature" "" "$origin" exit 0 fi # Créer/basculer vers une feature branch git_ensure_cleancheckout + is_any_branch "$feature" develop feature || die "$release: ce n'est pas une feature branch" + r=0 if git_have_branch "$feature"; then - git checkout "$feature" + git checkout "$feature" || r=$? + elif git_have_rbranch "$feature" "$origin"; then + git checkout "$feature" || r=$? else estepn "\ Vous allez créer la nouvelle feature branch ${COULEUR_VERTE}$feature${COULEUR_NORMALE} @@ -118,7 +156,11 @@ Vous allez créer la nouvelle feature branch ${COULEUR_VERTE}$feature${COULEUR_N git_ensure_branch "$feature" "$source" "$origin" [ $? -eq 2 ] && die "Impossible de créer la branche $feature. Veuillez vérifier que la branche $source existe" - git checkout "$feature" + git checkout "$feature" || r=$? + fi + if [ "$r" -eq 0 ]; then + # éventuellement fast-forwarder automatiquement + git_fast_forward "$feature" "" "$origin" fi exit $? @@ -127,7 +169,7 @@ fi feature="$1" if [ -n "$feature" ]; then is_feature_branch "$feature" || die "$feature: ce n'est pas une feature branch" - git_have_branch "$feature" || die "$feature: branche invalide" + git_have_branch "$feature" || die "$feature: branche introuvable" elif is_feature_branch "$branch"; then feature="$branch" fi @@ -149,30 +191,56 @@ if [ "$action" == merge ]; then fi fi - estepn "\ -Intégration de la feature branch ${COULEUR_VERTE}$feature${COULEUR_NORMALE} -dans la branche de destination ${COULEUR_BLEUE}develop${COULEUR_NORMALE}" + estepn "Intégration ${COULEUR_VERTE}$feature${COULEUR_NORMALE} --> ${COULEUR_BLEUE}develop${COULEUR_NORMALE}" ask_yesno "Voulez-vous continuer?" O || die - git checkout develop - git merge "$feature" -m "Intégration de la feature branch $feature" --no-ff || die + # calculer la suite des modifications + mergemsg="Intégration de la branche $feature" + if [ -n "$merge_log" ]; then + setx mergebase=git merge-base develop "$feature" + setx modifs=git log --oneline "$mergebase..$feature" + [ -n "$modifs" ] && mergemsg="$mergemsg +$modifs" + fi + + git checkout develop || die + git merge "$feature" -m "$mergemsg" --no-ff || die + + # mettre à jour la branche sur laquelle on se trouve + setx branch=git_get_branch + + [ -n "$merge_delete" ] && action=delete +fi + +if [ "$action" == delete ]; then + if [ -z "$force_delete" ]; then + # vérifier que la branche a été fusionnée + git_is_merged "$feature" develop || die "Refus de supprimer la branche $feature: elle n'a pas été fusionnée dans develop" + fi + + if [ "$branch" == "$feature" ]; then + # si on est sur la branche en question, en sortir pour pouvoir la + # supprimer + git checkout develop || die + fi estepi "Suppression de la branche locale" - git branch -d "$feature" + git branch -D "$feature" if git_have_remote "$origin"; then if [ -z "$UTOOLS_VCS_OFFLINE" ]; then estepi "Suppression de la branche distante" git push "$origin" ":$feature" - else + elif git_have_rbranch "$feature" "$origin"; then eimportant "\ -La branche $feature n'a plus lieu d'être, mais la configuration actuelle interdit de la supprimer dans le dépôt distant. +La branche $origin/$feature n'a plus lieu d'être, mais la configuration actuelle interdit de la supprimer. Veuillez le faire manuellement avec la commande suivante: $(quoted_args git push "$origin" ":$feature")" fi fi +fi -elif [ "$action" == diff ]; then +if [ "$action" == diff ]; then if [ -n "$log" ]; then if [ -n "$feature" ]; then git log ${diff:+-p} develop.."$feature" diff --git a/prel b/prel new file mode 100755 index 0000000..d7e2841 --- /dev/null +++ b/prel @@ -0,0 +1,448 @@ +#!/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 + +source "$(dirname "$0")/lib/ulib/ulib" || exit 1 +urequire DEFAULTS ptools + +# 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 + $scriptname -u [SOURCE] + $scriptname -c [RELEASE [SOURCE]] + $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. +- 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. +- 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 + + -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 + 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 + 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. + -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 par 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. + + -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 + Supprimer une branche de release, même si elle n'a pas encore été + fusionnée dans la branche master + + -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= +update= +incversion= +pver_opts=() +write=1 +edit_changes= +merge= +force_delete= +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' \ + -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' \ + -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 + else + # checkout par défaut + action=checkout + fi +fi + +if [ -n "$projdir" ]; then + cd "$projdir" || die +fi + +git_ensure_gitvcs + +setx branch=git_get_branch + +if [ "$action" == update ]; then + setx oldver=pver -g "" + newver= + + if [ "$incversion" == auto ]; then + if [ ${#pver_opts[*]} -gt 0 ]; then + # des options ont été spécifiées, les honorer + setx newver=pver -s "$oldver" "${pver_opts[@]}" + release="release-$newver" + else + # sinon, prendre une décision en fonction des branches de release + # qui existent déjà + setx -a branches=list_release_branches "$origin" + 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" \ + -t "Basculer vers une branche de release" \ + -m "Veuillez choisir la branche vers laquelle basculer" + fi + fi + fi + case "$incversion" in + menu) + setx majorv=pver -s "$oldver" -ux "${pver_opts[@]}" + setx minorv=pver -s "$oldver" -uz "${pver_opts[@]}" + setx patchlevelv=pver -s "$oldver" -up "${pver_opts[@]}" + release="release-$minorv" + branches=("release-$majorv" "release-$minorv" "release-$patchlevelv" master) + simple_menu release branches \ + -t "Basculer vers une nouvelle branche de release" \ + -m "Veuillez choisir la branche à créer" + [ "$release" != master ] && newver="${release#release-}" + ;; + major) + setx newver=pver -s "$oldver" -ux "${pver_opts[@]}" + release="release-$newver" + ;; + minor) + setx newver=pver -s "$oldver" -uz "${pver_opts[@]}" + release="release-$newver" + ;; + patchlevel) + setx newver=pver -s "$oldver" -up "${pver_opts[@]}" + release="release-$newver" + ;; + esac + + set -- "$release" "$1" + action=checkout +fi + +if [ "$action" == checkout ]; then + release="$1" + source="${2:-develop}" + + if [ -z "$release" ]; then + setx -a branches=list_release_branches "$origin" + + 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]}" + 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" \ + -t "Basculer vers une branche de release" \ + -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 + git_fast_forward "$release" "" "$origin" + exit 0 + fi + + # Créer/basculer vers une release branch + git_ensure_cleancheckout + is_any_branch "$release" master release || die "$release: ce n'est pas une branche de release" + r=0 + if git_have_branch "$release"; then + git checkout "$release"; r=$? + elif git_have_rbranch "$release"; then + git checkout "$release"; r=$? + else + estepn "\ +Vous allez créer la nouvelle branche de release ${COULEUR_VERTE}$release${COULEUR_NORMALE} +à partir de la branche source ${COULEUR_BLEUE}$source${COULEUR_NORMALE}" + ask_yesno "Voulez-vous continuer?" O || die + + git_ensure_branch "$release" "$source" "$origin" + [ $? -eq 2 ] && die "Impossible de créer la branche $release. Veuillez vérifier que la branche $source existe" + 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 + 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" + 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" + fi + fi + if [ "$r" -eq 0 ]; then + # éventuellement fast-forwarder automatiquement + git_fast_forward "$release" "" "$origin" + fi + + if [ "$r" -eq 0 -a -n "$merge" ]; then + # mettre à jour la branche sur laquelle on se trouve + setx branch=git_get_branch + + set -- "$release" + action=merge + else + exit "$r" + fi +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 + is_release_branch "$release" || die "$release: ce n'est pas une branche de release" + elif ! is_develop_branch "$release"; then + die "Aucune branche de release n'existe, vous devez fusionner à partir de develop" + fi + git_have_branch "$release" || die "$release: branche introuvable" +elif is_release_branch "$branch"; then + release="$branch" +fi + +if [ "$action" == merge ]; then + confirm= + + if [ -z "$release" ]; then + if [ ${#branches[*]} -eq 0 ]; then + ewarn "Aucune branche de release n'a été préparée." + ewarn "La branche develop sera fusionnée directement dans master." + 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" \ + -t "Choix de la branche de release" \ + -m "Veuillez choisir la branche" + fi + fi + + estepn "Intégration ${COULEUR_VERTE}$release${COULEUR_NORMALE} --> ${COULEUR_BLEUE}master${COULEUR_NORMALE}" + ask_yesno $confirm "Voulez-vous continuer?" O || die + + git checkout master || die + git merge "$release" -m "Intégration de la branche $release" --no-ff || die + + 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 + estepn "Création du tag $newver" + git tag --force "$newver" || die + fi + + if [ "$release" != develop ]; then + estepn "Intégration ${COULEUR_VERTE}$release${COULEUR_NORMALE} --> ${COULEUR_BLEUE}develop${COULEUR_NORMALE}" + git checkout develop + git merge "$release" -m "Intégration de la branche $release" --no-ff || die + fi + + # mettre à jour la branche sur laquelle on se trouve + git checkout master || die + setx branch=git_get_branch + + action=delete +fi + +if [ "$action" == delete -a "$release" != develop ]; then + 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. +Veuillez le faire manuellement avec la commande suivante: + $(qvals git push "$origin" ":$release")" + fi + fi +fi + +if [ "$action" == diff ]; then + 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 +fi diff --git a/pver b/pver index e19fa25..cb10543 100755 --- a/pver +++ b/pver @@ -1,9 +1,9 @@ #!/bin/bash # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 source "$(dirname "$0")/lib/ulib/ulib" || exit 1 -urequire DEFAULTS semver +urequire DEFAULTS ptools -function display_help() { +function pver_display_help() { uecho "$scriptname: gérer des numéros de version selon les règles du versionage sémantique v2.0.0 (http://semver.org/) USAGE @@ -14,6 +14,10 @@ OPTIONS Gérer le numéro de version se trouvant dans le fichier spécifié. Le fichier est créé si nécessaire. C'est l'option par défaut si un fichier nommé VERSION.txt se trouve dans le répertoire courant. + -e, --maven POMFILE + Gérer le numéro de version se trouvant dans le fichier pom.xml spécifié. + Le fichier DOIT exister. C'est l'option par défaut si un fichier nommé + pom.xml se trouve dans le répertoire courant. -F, --file-string VERSIONFILE Prendre pour valeur de départ le contenu du fichier VERSIONFILE (qui vaut par défaut VERSION.txt) @@ -26,6 +30,10 @@ OPTIONS --show Afficher le numéro de version. C'est l'action par défaut + --allow-empty + Supporter que la version puisse ne pas être spécifiée ni trouvée. Dans + ce cas, ne pas assumer que la version effective est 0.0.0 + Avec --show et --update, ne rien afficher si la version est vide. --check Vérifier que le numéro de version est conforme aux règles du versionage sémantique @@ -50,6 +58,10 @@ OPTIONS Spécifier un nouveau numéro de version qui écrase la valeur actuelle. Cette option ne devrait pas être utilisée en temps normal parce que cela va contre les règles du versionage sémantique. + --prel + Spécifier un nouveau numéro de version qui écrase la valeur actuelle. Le + numéro de version est obtenu à partir du nom de la branche git courante, + qui doit être de la forme release-VERSION -u, --update Mettre à jour le numéro de version. @@ -80,328 +92,10 @@ OPTIONS Spécifier un identifiant de build, à ajouter au numéro de version. -M, --vcs-metadata Spécifier l'identifiant à partir de la révision actuelle dans le - gestionnaire de version. Note: pour le moment, seul git est supporté." + gestionnaire de version. Note: pour le moment, seul git est supporté. + --add-metadata ID + Ajouter l'identifiant spécifié à la valeur actuelle, au lieu de la + remplacer. Séparer l'identifiant de la valeur précédente avec un '.'" } -DEFAULT_FILE=VERSION.txt - -action=auto -source=auto -file= -git= -version= -convert=auto -operator= -oversion= -setversion= -incversion= -setprelease= -setalpha= -setbeta= -setrc= -setrelease= -setmetadata= -vcsmetadata= -parse_opts "${PRETTYOPTS[@]}" \ - --help '$exit_with display_help' \ - -f:,--file: '$set@ file; source=file' \ - -F:,--file-string: '$set@ file; source=file-string' \ - -g:,--git-string: '$set@ git; source=git-string' \ - -s:,--string: '$set@ version; source=string' \ - --show action=show \ - --check action=check \ - --convert convert=1 \ - --no-convert convert= \ - --eq: '$action=compare; operator=eq; set@ oversion' \ - --ne: '$action=compare; operator=ne; set@ oversion' \ - --lt: '$action=compare; operator=lt; set@ oversion' \ - --le: '$action=compare; operator=le; set@ oversion' \ - --gt: '$action=compare; operator=gt; set@ oversion' \ - --ge: '$action=compare; operator=ge; set@ oversion' \ - -v:,--set-version: '$action=update; set@ setversion; incversion=' \ - -u,--update '$action=update; [ -z "$incversion" ] && incversion=auto' \ - --menu '$action=update; incversion=menu' \ - -x,--major '$action=update; incversion=major' \ - -z,--minor '$action=update; incversion=minor' \ - -p,--patchlevel '$action=update; incversion=patchlevel' \ - -l:,--prelease:,--prerelease: '$action=update; set@ setprelease; [ -z "$setprelease" ] && { setalpha=; setbeta=; setrc=; setrelease=1; }' \ - -a,--alpha '$action=update; setalpha=1; setbeta=; setrc=; setrelease=' \ - -b,--beta '$action=update; setalpha=; setbeta=1; setrc=; setrelease=' \ - -r,--rc '$action=update; setalpha=; setbeta=; setrc=1; setrelease=' \ - -R,--release,--final '$action=update; setalpha=; setbeta=; setrc=; setrelease=1' \ - -m:,--metadata: '$action=update; set@ setmetadata' \ - -M,--vcs-metadata '$action=update; vcsmetadata=1' \ - @ args -- "$@" && set -- "${args[@]}" || die "$args" - -# Calculer la source -if [ "$source" == auto ]; then - source=file - for i in "$DEFAULT_FILE" version.txt; do - if [ -f "$i" ]; then - file="$i" - break - fi - done -elif [ "$source" == file ]; then - [ "$action" == auto ] && action=update -fi -[ "$source" == file -a -z "$file" ] && file="$DEFAULT_FILE" -[ "$action" == auto ] && action=show - -# Lire la version -if [ "$source" == file ]; then - [ -f "$file" ] && version="$(<"$file")" -elif [ "$source" == file-string ]; then - if [ -z "$file" ]; then - file="$DEFAULT_FILE" - elif [ -d "$file" ]; then - file="$file/$DEFAULT_FILE" - fi - [ -f "$file" ] && version="$(<"$file")" - file= -elif [ "$source" == git-string ]; then - splitfsep2 "$git" : branch name - [ -n "$branch" ] || branch=master - [ -n "$name" ] || name="$DEFAULT_FILE" - if git rev-parse --verify --quiet "$branch:$name" >/dev/null; then - version="$(git cat-file blob "$branch:$name" 2>/dev/null)" - fi -fi -[ -n "$version" ] || version=0.0.0 - -# Conversion éventuelle du numéro de version -psemver_parse "$version" -[ -n "$valid" ] && convert= -if [ "$convert" == auto ]; then - [ -z "$valid" ] && convert=1 -fi -if [ -n "$convert" ]; then - mversion="$(awkrun version="$version" ' -function nbdot(s) { - gsub(/[^.]/, "", s) - return length(s) -} -BEGIN { - if (version ~ /[0-9]+(\.[0-9]+)*(-r[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9][0-9][0-9])?$/) { - metadata = "" - # traiter release date - pos = length(version) - 12 - if (pos > 0) { - rdate = substr(version, pos + 3) - metadata = substr(rdate, 7, 4) substr(rdate, 4, 2) substr(rdate, 1, 2) - version = substr(version, 1, pos) - } - # traiter metadata - match(version, /[0-9]+(\.[0-9]+(\.[0-9]+)?)?/) - pos = RLENGTH - if (pos < length(version)) { - if (metadata != "") metadata = metadata "." - metadata = metadata substr(version, pos + 2) - } - version = substr(version, 1, pos) - # ajouter les éléments manquants - while (nbdot(version) < 2) { - version = version ".0" - } - # afficher la version migrée au format semver - if (metadata != "") print version "+" metadata - else print version - } -}')" - if [ -n "$mversion" ]; then - version="$mversion" - psemver_parse "$version" - fi -fi - -# Actions -if [ "$action" == show ]; then - if isatty; then - estepi "La version actuelle est $version" - else - echo "$version" - fi - exit 0 -fi - -if [ "$action" == check ]; then - [ -n "$valid" ] || die "Numéro de version invalide: $version" - -elif [ "$action" == compare ]; then - psemver_parse "$oversion" o - - case "$operator" in - eq|same) - for var in valid major minor patchlevel; do - ovar="o$var" - [ "${!var}" == "${!ovar}" ] || exit 1 - done - array_eq prelease oprelease || exit 1 - if [ "$operator" == same ]; then - array_eq metadata ometadata || exit 1 - fi - exit 0 - ;; - ne|diff) - for var in valid major minor patchlevel; do - ovar="o$var" - [ "${!var}" != "${!ovar}" ] && exit 0 - done - ! array_eq prelease oprelease && exit 0 - if [ "$operator" == diff ]; then - ! array_eq metadata ometadata && exit 0 - fi - exit 1 - ;; - lt) - [ -z "$valid" -a -z "$ovalid" ] && exit 1 - [ "$major" -lt "$omajor" ] && exit 0 - [ "$major" -gt "$omajor" ] && exit 1 - [ "$minor" -lt "$ominor" ] && exit 0 - [ "$minor" -gt "$ominor" ] && exit 1 - [ "$patchlevel" -lt "$opatchlevel" ] && exit 0 - [ "$patchlevel" -gt "$opatchlevel" ] && exit 1 - case "$(psemver_compare_prelease "" o)" in - lt) exit 0;; - esac - exit 1 - ;; - le) - [ -z "$valid" -a -z "$ovalid" ] && exit 1 - [ "$major" -lt "$omajor" ] && exit 0 - [ "$major" -gt "$omajor" ] && exit 1 - [ "$minor" -lt "$ominor" ] && exit 0 - [ "$minor" -gt "$ominor" ] && exit 1 - [ "$patchlevel" -lt "$opatchlevel" ] && exit 0 - [ "$patchlevel" -gt "$opatchlevel" ] && exit 1 - case "$(psemver_compare_prelease "" o)" in - lt|eq) exit 0;; - esac - exit 1 - ;; - gt) - [ -z "$valid" -a -z "$ovalid" ] && exit 1 - [ "$major" -lt "$omajor" ] && exit 1 - [ "$major" -gt "$omajor" ] && exit 0 - [ "$minor" -lt "$ominor" ] && exit 1 - [ "$minor" -gt "$ominor" ] && exit 0 - [ "$patchlevel" -lt "$opatchlevel" ] && exit 1 - [ "$patchlevel" -gt "$opatchlevel" ] && exit 0 - case "$(psemver_compare_prelease "" o)" in - gt) exit 0;; - esac - exit 1 - ;; - ge) - [ -z "$valid" -a -z "$ovalid" ] && exit 1 - [ "$major" -lt "$omajor" ] && exit 1 - [ "$major" -gt "$omajor" ] && exit 0 - [ "$minor" -lt "$ominor" ] && exit 1 - [ "$minor" -gt "$ominor" ] && exit 0 - [ "$patchlevel" -lt "$opatchlevel" ] && exit 1 - [ "$patchlevel" -gt "$opatchlevel" ] && exit 0 - case "$(psemver_compare_prelease "" o)" in - gt|eq) exit 0;; - esac - exit 1 - ;; - esac - -elif [ "$action" == update ]; then - [ -n "$valid" ] || die "Numéro de version invalide: $version" - - if [ -n "$file" ]; then - if [ -f "$file" ]; then - if isatty; then - estepi "La version actuelle est $version" - fi - else - if isatty; then - ask_yesno "Le fichier $(ppath "$file") n'existe pas. Faut-il le créer?" O || die - fi - fi - fi - - # forcer le numéro de version - if [ -n "$setversion" ]; then - psemver_setversion "$setversion" "" || die "Numéro de version invalide: $setversion" - fi - - # Calculer metadata - if [ -n "$vcsmetadata" ]; then - setmetadata="$(git rev-parse --short HEAD)" || die - fi - - # incrémenter les numéros de version - if [ "$incversion" == auto ]; then - if [ -n "$setrelease" -o -n "$setprelease" -o -n "$setmetadata" ]; then - incversion= - else - incversion=menu - fi - fi - if [ "$incversion" == menu ]; then - psemver_copy x; psemver_incmajor x; psemver_setprelease "$setprelease" x; psemver_setmetadata "$setmetadata" x; psemver_setvar versionx x - psemver_copy z; psemver_incminor z; psemver_setprelease "$setprelease" z; psemver_setmetadata "$setmetadata" z; psemver_setvar versionz z - psemver_copy p; psemver_incpatchlevel p; psemver_setprelease "$setprelease" p; psemver_setmetadata "$setmetadata" p; psemver_setvar versionp p - psemver_copy k; psemver_setprelease "$setprelease" k; psemver_setmetadata "$setmetadata" k; psemver_setvar versionk k - nextvs=( - "$versionx : maj incompatibles de l'API (-x)" - "$versionz : maj compatibles de l'API (-z)" - "$versionp : correction de bugs (-p)" - "$versionk : ne pas incrémenter la version" - ) - nextv="${nextvs[1]}" - simple_menu nextv nextvs \ - -t "Incrémenter le numéro de version" \ - -m "Veuillez choisir la prochaine version" - case "${nextv%)}" in - *-x) incversion=major;; - *-z) incversion=minor;; - *-p) incversion=patchlevel;; - *) incversion=;; - esac - fi - if [ -n "$incversion" ]; then - case "$incversion" in - major) psemver_incmajor;; - minor) psemver_incminor;; - patchlevel) psemver_incpatchlevel;; - esac - # Quand on incrémente, réinitialiser la valeur de prérelease et metadata - psemver_setprelease - psemver_setmetadata - fi - - # spécifier prerelease - if [ -n "$setrelease" ]; then - psemver_setprelease "" - elif [ -n "$setprelease" ]; then - psemver_setprelease "$setprelease" || die "Identifiant de pre-release invalide: $setprelease" - fi - if [ -n "$setalpha" ]; then - : #XXX - elif [ -n "$setbeta" ]; then - : #XXX - elif [ -n "$setrc" ]; then - : #XXX - fi - - # spécifier metadata - if [ -n "$setmetadata" ]; then - psemver_setmetadata "$setmetadata" || die "Identifiant de build invalide: $setmetadata" - fi - - # afficher le résultat final - psemver_setvar version - if [ -n "$file" ]; then - echo "$version" >"$file" - fi - if isatty; then - estepn "La nouvelle version est $version" - else - echo "$version" - fi -fi - -exit 0 +pver "$@" diff --git a/pz b/pz new file mode 100755 index 0000000..c8622d5 --- /dev/null +++ b/pz @@ -0,0 +1,66 @@ +#!/bin/bash +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +source "$(dirname "$0")/lib/ulib/ulib" || exit 1 +urequire DEFAULTS vcs ptools + +function display_help() { + uecho "$scriptname: faire une archive du projet + +USAGE + $scriptname + +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. + -d, --destdir DESTDIR + Spécifier le répertoire dans lequel générer l'archive. Par défaut, + prendre le répertoire parent du répertoire de base du dépôt." +} + +projdir= +destdir= +parse_opts "${PRETTYOPTS[@]}" \ + --help '$exit_with display_help' \ + -C:,--projdir: projdir= \ + -d:,--destdir: destdir= \ + @ args -- "$@" && set -- "${args[@]}" || die "$args" + +if [ -n "$projdir" ]; then + cd "$projdir" || die + git_ensure_gitvcs +else + git_ensure_gitvcs + setx projdir=git rev-parse --show-toplevel + cd "$projdir" || die +fi +setx projdir=pwd + +if [ -z "$destdir" ]; then + setx destdir=dirname -- "$projdir" +fi + +setx name=basename -- "$projdir" +setx branch=git rev-parse --short HEAD 2>/dev/null +setx version=pver --show --allow-empty +[ -n "$version" ] && setx version=pver --show --string "$version" --add-metadata "$branch" +[ -n "$version" ] || version="+$branch" + +if check_sysinfos -d debian -v squeeze-; then + # git archive sous debian squeeze a un bug: il génère un fichier tar au lieu + # d'un fichier tar compressé. Nous ferons donc la compression nous même. + dest="$destdir/$name${version:+-$version}.tar" + gzip=1 +else + dest="$destdir/$name${version:+-$version}.tar.gz" + gzip= +fi + +estep "Création de $(ppath "$dest")" +git archive -o "$dest" --prefix="$name${version:+-$version}/" HEAD || die +[ -n "$gzip" ] || exit 0 + +estep "Compression de l'archive" +gzip -f "$dest" diff --git a/todo/prel b/todo/prel deleted file mode 100755 index 9ae6370..0000000 --- a/todo/prel +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash -# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 -source "$(dirname "$0")/lib/ulib/ulib" || exit 1 -urequire DEFAULTS ptools - -# XXX ajouter la possibilité de faire des pré-releases, --alpha, --beta, --rc -# les pré-releases restent dans la branche de release, et vivent leur vie, -# jusqu'à la release finale qui est mergée dans master. Il faudrait aussi une -# option pour merger les modifications de la branche de release dans develop - -function display_help() { - uecho "$scriptname: basculer sur une branche de release - -USAGE - $scriptname [options] [SOURCE] - -- Vérifier s'il n'y a pas de modifications locales. Sinon, proposer de faire un - commit ou un stash. -- Si aucune branche de release n'existe, assumer -u -z pour préparer une release - mineure. Sinon, basculer simplement sur la branche de release. - -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 - -u, --update - Préparer une release. Utiliser une des options -x, -z ou -p pour - spécifier le type de release à préparer. S'il faut créer une nouvelle - branche, la baser sur la branche SOURCE, qui vaut par défaut develop - -x, --major - -z, --minor - -p, --patchlevel - Utilisé avec l'option -u, préparer respectivement une release majeure, - mineure (par défaut), et pour correction de bug. - -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. - Si la branche actuelle est une branche de topic et qu'il n'existe aucune - branche de release, assumer les options -u -z -m - -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 -parse_opts "${PRETTYOPTS[@]}" \ - --help '$exit_with display_help' \ - -C:,--projdir: projdir= \ - -O:,--origin: origin= \ - -o,--offline UTOOLS_VCS_OFFLINE=1 \ - --online UTOOLS_VCS_OFFLINE= \ - @ args -- "$@" && set -- "${args[@]}" || die "$args" - -if [ -n "$projdir" ]; then - cd "$projdir" || die -fi - -git_ensure_gitvcs diff --git a/uproject b/uproject index 8c2b530..6b22edf 100755 --- a/uproject +++ b/uproject @@ -66,6 +66,9 @@ COMMANDS release, ou de correction de bugs. Lancer chaque commande avec --help pour les détails. Nécessite git. + archive + Créer une archive du projet courant. Nécessite git. + annex [args] Lancer git annex avec les arguments spécifiés. xadd @@ -106,12 +109,12 @@ SCRIPT_ALIASES=( pv:vcs pa:add prm:remove pcp:copy pmv:move pmd:mkdir pci:commit pu:update pp:push pdiff:diff + pclone:clone + pcrone:crone pxx:annex pxa:xadd pxu:xunlock pxc:xcopy pxd:xdrop pxm:xmove pxg:xget pxs:xsync pxw:xwhereis pxinitial:xinitial - pclone:clone - pcrone:crone pnew:new pgr:grep paddml:addml @@ -130,6 +133,7 @@ CMD_ALIASES=( p:push version:pver ver:pver develop:pdev dev:pdev release:prel rel:prel hotfix:pfix fix:pfix + archive:pz arch:pz xx:annex xa:xadd xu:xunlock @@ -144,7 +148,7 @@ CMD_ALIASES=( DEFAULT_CMD=status PY_CMDS=(new) VCS_CMDS=(getvcs getroot getrepos geturl vcs add remove copy move mkdir commit status update push diff tag) -SH_CMDS=(pver pdev prel pfix) +SH_CMDS=(pver pdev prel pfix pz) GITANNEX_CMDS=(annex xadd xunlock xcopy xdrop xmove xget xsync xwhereis xinitial) ML_CMDS=(printml addml)