nutools/uversion

395 lines
13 KiB
Bash
Executable File

#!/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
function 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
$scriptname [options]
OPTIONS
-f, --file VERSIONFILE
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.
-g, --git [branch:]VERSIONFILE
Prendre pour valeur de départ le contenu du fichier VERSIONFILE (qui
vaut par défaut VERSION.txt) dans la branche BRANCH (qui vaut par défaut
master) du dépôt git situé dans le répertoire courant.
-s, --string VERSION
Prendre pour valeur de départ le numéro de version spécifié
--show
Afficher le numéro de version. C'est l'action par défaut
--check
Vérifier que le numéro de version est conforme aux règles du versionage
sémantique
--convert
--no-convert
Activer (resp. désactiver) la conversion automatique. Par défaut, si la
version est au format classique 'x.z[.p]-rDD/MM/YYYY', elle est
convertie automatiquement au format sémantique x.z.p+rYYYYMMDD
--eq VERSION
--ne VERSION
--lt VERSION
--le VERSION
--gt VERSION
--ge VERSION
--same VERSION
--diff VERSION
Comparer avec la version spécifiée. Les opérateurs --eq, --ne, --lt,
--le, --gt, et --ge ignorent l'identifiant de build (comme le demande la
règle du versionage sémantique). Les opérateurs --same et --diff
comparent aussi les identifiants de build.
-v, --set-version VERSION
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.
-u, --update
Mettre à jour le numéro de version.
--menu
Afficher un menu permettant de choisir le composant de la version à
incrémenter
-x, --major
Augmenter le numéro de version majeure
-z, --minor
Augmenter le numéro de version mineure. C'est la valeur par défaut.
-p, --patchlevel
Augmenter le numéro de patch
-l, --prelease ID
Spécifier un identifiant de pré-release, à ajouter au numéro de version.
-a, --alpha
-b, --beta
-r, --rc
Spécifier une pré-release de type alpha, beta, ou rc. Si la version est
déjà dans ce type, augmenter la dernière valeur numérique des composants
de l'identifiant, e.g. alpha deviant alpha.1, beta-1.2 devient beta-1.3,
rc1 devient rc2
XXX ces fonctions ne sont pas encore implémentées
-R, --final, --release
Supprimer l'identifiant de prérelease
-m, --metadata ID
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é."
}
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' \
-g:,--git: '$set@ git; source=git' \
-s:,--string: '$set@ version; source=' \
--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 VERSION.txt 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=VERSION.txt
[ "$action" == auto ] && action=show
# Lire la version
if [ "$source" == file ]; then
[ -f "$file" ] && version="$(<"$file")"
[ -n "$version" ] || version=0.0.0
elif [ "$source" == git ]; then
splitfsep2 "$git" : branch name
[ -n "$branch" ] || branch=master
[ -n "$name" ] || name=VERSION.txt
if git rev-parse --verify --quiet "$branch:$name" >/dev/null; then
version="$(git cat-file blob "$branch:$name" 2>/dev/null)"
fi
[ -n "$version" ] || version=0.0.0
fi
# Conversion éventuelle du numéro de version
psemver_parse "$version"
if [ "$convert" == auto ]; then
[ -z "$valid" ] && convert=1 || convert=
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