devscript: add command get_release_tag

update RELEASING.md accordingly
This commit is contained in:
Roland Walker
2014-01-30 10:49:00 -05:00
parent c9f3c3c347
commit a7e779bb71
2 changed files with 210 additions and 20 deletions
+170
View File
@@ -0,0 +1,170 @@
#!/bin/bash
#
# get_release_tag
#
set -e; # exit on any uncaught error
set +o histexpand; # don't expand history expressions
shopt -s nocasematch; # case-insensitive regular expressions
opt_next='';
opt_latest='';
opt_verbose='';
die () {
local message="$@";
if ! [[ $message =~ "\n"$ ]]; then
message="${message}\n"
fi
printf "$message" 1>&2
exit 1
}
cd_to_project_root () {
local script_dir="$(/usr/bin/dirname $0)"
cd "$script_dir"
local git_root="$(git rev-parse --show-toplevel)"
if [[ -z "$git_root" ]]; then
die "Could not find git project root"
fi
cd "$git_root"
}
verify_git_object_is_new () {
if git rev-parse --verify "$1" >/dev/null 2>&1; then
die "\nERROR: proposed new tag: '$1' already exists as a commit object\n\n"
fi
}
sanity_check_parsed_version () {
if [[ $# -ne 3 ]]; then
die "Error: can't parse version tag, wrong number of elements"
fi
if ! [[ $1 =~ ^v[0-9]+$ ]]; then
die "Error: can't parse version tag, does not start with v[0-9]"
fi
}
output_proposed_tag () {
local new_tag="$1.$2.$3"
sanity_check_parsed_version "$@"
verify_git_object_is_new "$new_tag"
if [[ -n "$opt_verbose" ]]; then
printf "Latest tag\t$latest_tag\n"
printf "Proposed new tag\t$new_tag\n"
else
printf "$new_tag\n"
fi
}
generate_next_major_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version "${version_elts[@]}"
version_elts[0]="${version_elts[0]#v}" # mangle v<digit> into number
(( version_elts[0] += 1 )) # increment version field
version_elts[0]="v${version_elts[0]}" # restore text v<digit>
version_elts[1]='0' # reset minor field
version_elts[2]='0' # reset patch field
output_proposed_tag "${version_elts[@]}"
}
generate_next_minor_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1";
sanity_check_parsed_version "${version_elts[@]}"
(( version_elts[1] += 1 )) # increment minor field
version_elts[2]='0' # reset patch field
output_proposed_tag "${version_elts[@]}"
}
generate_next_patch_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version ${version_elts[@]}
(( version_elts[2] += 1 )) # increment patch field
output_proposed_tag "${version_elts[@]}"
}
process_args () {
local arg
for arg in "$@"; do
if [[ $arg =~ ^-+h(elp)?$ ]]; then
printf "get_release_tag [ -latest | -next | -patch | -major | -verbose | -help ]
Retrieve or calculate a release tag.
Arguments:
-latest Show the most recent tag in the repository, which is typically
the designation of the latest release. This is the default
when invoked with no arguments.
-next Calculate the next minor-release tag bump and return it.
-patch Calculate the next patch-release tag bump and return it.
Overrides -next if both are given.
-major Calculate the next major-release tag bump and return it.
Overrides -next if both are given.
-verbose Output a table, possibly including both latest existing and
proposed new tags.
See RELEASING.md for more information.
"
exit
elif [[ $arg =~ ^-+v(erbose)?$ ]]; then
opt_verbose='true'
elif [[ $arg =~ ^-+next$ ]]; then
if [[ -z "$opt_next" ]]; then
opt_next='minor'
fi
elif [[ $arg =~ ^-+patch$ ]]; then
if [[ "$opt_next" == 'major' ]]; then
die "Error: -patch is incompatible with -major";
fi
opt_next='patch'
elif [[ $arg =~ ^-+major$ ]]; then
if [[ "$opt_next" == 'patch' ]]; then
die "Error: -patch is incompatible with -major";
fi
opt_next='major'
elif [[ $arg =~ ^-+latest$ ]]; then
opt_latest='true'
else
die "Error: unknown argument '$arg'"
fi
if [[ -n "$opt_latest" && -n "$opt_next" ]]; then
die "Error: -latest is incompatible with -next/-patch/-major"
fi
done
}
_get_release_tag () {
cd_to_project_root;
local latest_tag="$(git describe --tags --abbrev=0 2>/dev/null)"
if [[ -z "$latest_tag" ]]; then
die "Error: no recent tag found"
elif [[ -z "$opt_next" ]]; then
if [[ -n "$opt_verbose" ]]; then
printf "Latest tag\t"
fi
printf "$latest_tag\n"
elif [[ "$opt_next" == 'major' ]]; then
generate_next_major_tag "$latest_tag"
elif [[ "$opt_next" == 'minor' ]]; then
generate_next_minor_tag "$latest_tag"
elif [[ "$opt_next" == 'patch' ]]; then
generate_next_patch_tag "$latest_tag"
else
die "Error: should not happen. Unknown argument?"
fi
}
process_args "$@";
_get_release_tag;
#