##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ## Fonctions pour la gestion des projets ##@cooked nocomments ##@include vcs ##@include semver uprovide ptools urequire vcs semver 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-' } function list_hotfix_branches() { git_list_branches | grep '^hotfix-' } function list_feature_branches() { git_list_branches | 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 convert=auto local operator= local oversion= local setversion= local incversion= local setprelease= local setalpha= local setbeta= local setrc= local setrelease= local setmetadata= 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 \ --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: '$action=update; set@ setmetadata' \ -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" ] || 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 { ### 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 isatty; then estepi "La version actuelle est $version" else echo "$version" fi return 0 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 [ -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" ]; 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" || { 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 # 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 }