aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/build/setver.sh180
1 files changed, 157 insertions, 23 deletions
diff --git a/bin/build/setver.sh b/bin/build/setver.sh
index 470e529..ae8b048 100755
--- a/bin/build/setver.sh
+++ b/bin/build/setver.sh
@@ -2,7 +2,8 @@
#
# Sets roverlay's version.
#
-# Usage: setver [-S,--src <dir>] [--pretend] [--suffix <str>]
+# Usage: setver [-S,--src <dir>] [--pretend] [--suffix <str>] [--reset]
+# [--git-add] [--git-commit] [--force-commit] [--git-tag]
# [+,pbump|++,mbump|Mbump|[setver] <ver>]
#
# Actions:
@@ -15,40 +16,140 @@
# -S, --src <dir> -- set roverlay source directory (default: $PWD)
# --pretend -- just show what would be done
# --suffix <str> -- replace old version suffix with <str>
+# -l, --list-files -- just list files that would be edited by this script
+# (usage example: setver -l | xargs git checkout HEAD --)
+# --reset -- check out VERSION file from git HEAD before doing anything
+# --git-add -- git-add modified files
+# --git-commit -- commit changes (commit message: "roverlay <newver>")
+# --force-commit -- enforce git commit (allow other files)
+# --git-tag -- run git-tag <newver> after git-commit
#
+set -e
set -u
-IFS_DEFAULT="${IFS}"
+readonly IFS_DEFAULT="${IFS}"
-PY_FILES_TO_EDIT="roverlay/core.py setup.py"
+readonly PY_FILES_TO_EDIT="roverlay/core.py setup.py"
+readonly X_GIT="${X_GIT:-git}"
+# get_git_commit_message ( new_version, **commit_msg! )
+#
+# Creates a commit message and stores it in $commit_msg.
+# An empty str can be set if no commit should be made.
+#
+get_git_commit_message() {
+ commit_msg="roverlay ${1:?}"
+}
+
+# get_git_tag ( new_version, **tag! )
+#
+# Creates a git tag str and stores it in $tag.
+# An empty str suppresses tag creation.
+#
+get_git_tag() {
+ tag="${1:?}"
+}
+# @noreturn die ( [message], [exit_code] ), raises exit($exit_code)
+#
+# Lets the script die.
+#
die() {
- echo "${1:-unknown error.}" 1>&2; exit ${2:-2};
+ echo "${1:+died: }${1:-died.}" 1>&2; exit ${2:-2};
+}
+
+# autodie ( *cmdv )
+#
+# Runs *cmdv and dies on non-zero return.
+# ("set -ex" is too verbose)
+#
+autodie() {
+ "$@" || die "command '${*}' returned ${?}." ${?}
}
+# parse_version ( version_str, **major!, **minor!, **plvl!, **suffix! )
+#
+# Splits a version_str into its components.
+#
+# Example: 0.2.6-pre1 => major=0 minor=2 plvl=6 suffix=-pre1
+#
parse_version() {
+ unset -v major minor plvl suffix
local IFS="."
set -- ${1}
IFS="${IFS_DEFAULT}"
- [ ${#} -ge 3 ] || return 2
+ [ -n "${1-}" ] && [ -n "${2-}" ] && [ -n "${3-}" ] || return 2
major="${1:?}"
minor="${2:?}"
plvl="${3:?}"
shift 3 || die "error in parse_version()"
- suffix="${*}"
+ suffix=
+ while [ ${#} -gt 0 ]; do suffix="${suffix}.${1}"; shift; done
+ suffix="${suffix#.}"
}
+# inc ( k, **v0! )
+#
+# Increments $k by one and stores the result in $v0.
+#
inc() {
- v0=$(( ${1} + 1 ))
+ v0=$(( ${1:?} + 1 ))
+ # unlikely:
[ ${v0} -gt ${1} ] || die "overflow"
}
+# do_git_add ( *files, **want_gitadd, **X_GIT )
+#
+do_git_add() {
+ ${want_gitadd} || return 0
+ printf "git-add: %s\n" "${*}"
+ ${want_pretend} || autodie "${X_GIT}" add -- "$@"
+}
+
+# do_git_commit_and_tag (
+# version_str, numfiles_changed,
+# **want_gitcommit, **want_forcecommit, **want_gittag, **X_GIT
+# )
+#
+do_git_commit_and_tag() {
+ ${want_gitcommit} || return 0
+ local commit_msg commit_type tag
+
+ autodie get_git_commit_message "${1}"
+ autodie get_git_tag "${1}"
+
+ if [ -z "${commit_msg}" ]; then
+ return 0
+ elif ${want_pretend}; then
+ commit_type=maybe
+ elif \
+ [ $(git status --porcelain -- . | grep -c -- ^[MADRCU]) -eq ${2} ]
+ then
+ commit_type=clean
+ elif ${want_forcecommit}; then
+ commit_type=forced
+ else
+ die "cannot commit changes (try --force-commit)."
+ fi
+
+ printf "git-commit [%s]: %s\n" "${commit_type}" "${commit_msg}"
+ ${want_pretend} || autodie "${X_GIT}" commit -m "${commit_msg}"
+
+ ${want_gittag} && [ -n "${tag}" ] || return 0
+ printf "git-tag: %s\n" "${tag}"
+ ${want_pretend} || autodie "${X_GIT}" tag "${tag}"
+}
+
+
+# set defaults / parse args
+autodie hash "${X_GIT}"
S="${PWD}"
unset -v V
unset -v ACTION
unset -v new_suffix
-unset -v do_pretend
+
+readonly _boolvars="pretend gitadd gitcommit forcecommit gittag reset"
+for iter in ${_boolvars}; do eval "want_${iter}=false"; done
doshift=
while [ ${#} -gt 0 ]; do
@@ -56,15 +157,18 @@ while [ ${#} -gt 0 ]; do
case "${1}" in
'') : ;;
- '--src'|'-S')
- [ ${#} -ge 2 ] || die "argparse error"
+ -S|--src)
+ [ -n "${2-}" ] || die "one non-empty arg required after '${1}'."
doshift=2
S="${2:?}"
;;
- pretend|--pretend)
- do_pretend=true
- ;;
+ --pretend) want_pretend=true ;;
+ --reset) want_reset=true ;;
+ --git-add) want_gitadd=true ;;
+ --git-commit) want_gitcommit=true ;;
+ --force-commit) want_forcecommit=true ;;
+ --git-tag) want_gittag=true ;;
[Mmp]bump) ACTION="${1}" ;;
'+') ACTION=pbump ;;
@@ -72,18 +176,24 @@ while [ ${#} -gt 0 ]; do
*.*.*) ACTION=setver; V="${1}" ;;
setver)
- [ ${#} -ge 2 ] || die "argparse error"
+ [ -n "${2-}" ] || die "one non-empty arg required after '${1}'."
doshift=2
ACTION=setver
V="${2:?}"
;;
- suffix|--suffix)
- [ ${#} -ge 2 ] || die "argparse error"
+ --suffix)
+ [ -n "${2+SET}" ] || die "one arg required after '${1}'."
doshift=2
new_suffix="${2?}"
;;
+ -l|--list-files)
+ for fname in ${PY_FILES_TO_EDIT}; do echo "${fname}"; done
+ echo "VERSION"
+ exit 0
+ ;;
+
*)
die "unknown arg: ${1}" 64
;;
@@ -91,11 +201,20 @@ while [ ${#} -gt 0 ]; do
[ ${doshift} -eq 0 ] || shift ${doshift} || die "argparse: shift failed"
done
-: ${do_pretend:=false}
-OLDVER="$(cat "${S}/VERSION")"
-parse_version "${OLDVER}" || die "bad version: ${OLDVER}."
-[ -n "${new_suffix+SET}" ] || new_suffix="${suffix}"
+! { ${want_gittag} || ${want_forcecommit}; } || want_gitcommit=true
+! ${want_gitcommit} || want_gitadd=true
+
+readonly S ACTION
+for iter in ${_boolvars}; do readonly "want_${iter}"; done
+
+cd "${S}" || die "chdir ${S}"
+! ${want_reset} || autodie "${X_GIT}" checkout HEAD -- VERSION
+readonly OLDVER="$(cat "${S}/VERSION")" || die "failed to read ${S}/VERSION"
+autodie parse_version "${OLDVER}"
+: ${new_suffix="${suffix}"}
+
+# get new version
case "${ACTION-}" in
pbump)
inc "${plvl}"
@@ -113,19 +232,34 @@ case "${ACTION-}" in
true
;;
*)
- die "unknown or no action specified."
+ ${want_reset} || die "unknown or no action specified."
+ exit 0
;;
esac
+
+# edit files
q="\"\'"
re_pyfile_ver="^(\s*version\s*=\s*)[${q}]?([^\s;,${q}]*)[${q}]?(\s*[;,]?\s*)\$"
+v0=0
_fmt="edit %-18s: %8s -> %s\n"
for fname in ${PY_FILES_TO_EDIT}; do
+ inc "${v0}"
f="${S}/${fname}"
fver="$(sed -rn -e "s@${re_pyfile_ver}@\2@p" < "${f}")"
printf "${_fmt}" "${fname}" "${fver}" "${V}"
- ${do_pretend} || sed -r -e "s@${re_pyfile_ver}@\1\"${V}\"\3@" -i "${f}"
+ ${want_pretend} || \
+ autodie sed -r -e "s@${re_pyfile_ver}@\1\"${V}\"\3@" -i "${f}"
+ do_git_add "${f}"
done
+
+inc "${v0}"
printf "${_fmt}" "VERSION" "${OLDVER}" "${V}"
-${do_pretend} || echo "${V}" > "${S}/VERSION"
+${want_pretend} || echo "${V}" > "${S}/VERSION" || die "failed to write VERSION"
+do_git_add "${S}/VERSION"
+
+[ ${v0} -gt 0 ] || die "numfiles?"
+printf "edited %d files in total.\n" "${v0}"
+
+autodie do_git_commit_and_tag "${V}" "${v0}"