#!/bin/sh GIT_NOTARY_VERSION=2.3.1 GIT_NOTARY_NAMESPACE=${GIT_NOTARY_NAMESPACE:-'versioning'} # notes [branch] [base] [namespace] notes() { BRANCH=${1-'develop'} BASE=${2:-$(git describe --tags --abbrev=0)} NAMESPACE=${3:-${GIT_NOTARY_NAMESPACE}} git rev-list --topo-order ${BASE}..${BRANCH} --reverse | while read OBJECT; do printf "${OBJECT} " git notes --ref=${NAMESPACE} show ${OBJECT} 2> /dev/null || echo done | grep -E '(MAJOR|MINOR|PATCH)$' } # squash squash() { while read OBJECT_CHANGE; do OBJECT=$(echo ${OBJECT_CHANGE} | awk '{ print $1 }') CHANGE=$(echo ${OBJECT_CHANGE} | awk '{ print $2 }') case ${CHANGE} in MAJOR) RESULT=MAJOR;; MINOR) test "${RESULT}" != MAJOR && RESULT=MINOR;; PATCH) test -z "${RESULT}" && RESULT=PATCH;; esac done test ! -z "${RESULT}" && echo ${OBJECT} ${RESULT} } # squeeze squeeze() { case ${1} in d|down|f|first|o|old*) DIRECTION=DOWN;; u|up|l|last|n|new*) DIRECTION=UP;; *) echo 'git-notary squeeze requires a direction (up or down)' >&2 exit 23;; esac while read OBJECT_CHANGE; do OBJECT=$(echo ${OBJECT_CHANGE} | awk '{ print $1 }') CHANGE=$(echo ${OBJECT_CHANGE} | awk '{ print $2 }') if test "${CHANGE}" != "${LAST_CHANGE}"; then case ${DIRECTION} in DOWN) echo ${OBJECT} ${CHANGE};; UP) test ! -z "${LAST_OBJECT}" && echo ${LAST_OBJECT} ${LAST_CHANGE};; esac fi LAST_OBJECT=${OBJECT} LAST_CHANGE=${CHANGE} done test "${DIRECTION}" = UP && echo ${LAST_OBJECT} ${LAST_CHANGE} } # versions [initial] versions() { set -o errexit VERSION=${1:-$(git describe --tags --abbrev=0)} MAJOR=$(echo ${VERSION} | awk -F . '{ print $1 }') MINOR=$(echo ${VERSION} | awk -F . '{ print $2 }') PATCH=$(echo ${VERSION} | awk -F . '{ print $3 }') next() { echo ${1} + 1 | bc } while read OBJECT_CHANGE; do OBJECT=$(echo ${OBJECT_CHANGE} | awk '{ print $1 }') CHANGE=$(echo ${OBJECT_CHANGE} | awk '{ print $2 }') case ${CHANGE} in MAJOR) MAJOR=$(next ${MAJOR}) MINOR=0 PATCH=0 ;; MINOR) MINOR=$(next ${MINOR}) PATCH=0 ;; PATCH) PATCH=$(next ${PATCH}) ;; esac VERSION=${MAJOR}.${MINOR}.${PATCH} echo ${OBJECT} ${VERSION} done } # tags [--apply] tags() { while read OBJECT_TAG; do OBJECT=$(echo ${OBJECT_TAG} | awk '{ print $1 }') TAG=$(echo ${OBJECT_TAG} | awk '{ print $2 }') if test "${1}" = '--apply'; then git tag ${TAG} ${OBJECT} else echo git tag ${TAG} ${OBJECT} fi done } # fetch [remote] [namespace] fetch() { FORCE="" if test "${1:-}" = "--force"; then shift FORCE="+" fi REMOTE=${1:-'origin'} NAMESPACE=${2:-${GIT_NOTARY_NAMESPACE}} git fetch ${REMOTE} ${FORCE}refs/notes/${NAMESPACE}:refs/notes/${NAMESPACE} } # pull [remote] [namespace] [strategy] pull() { REMOTE=${1:-'origin'} NAMESPACE=${2:-${GIT_NOTARY_NAMESPACE}} STRATEGY=${3:-'theirs'} git fetch ${REMOTE} refs/notes/${NAMESPACE} env GIT_NOTES_REF=refs/notes/${NAMESPACE} git notes merge -s ${STRATEGY} FETCH_HEAD } # push [remote] [namespace] push() { REMOTE=${1:-'origin'} NAMESPACE=${2:-${GIT_NOTARY_NAMESPACE}} git push --no-verify ${REMOTE} refs/notes/${NAMESPACE} } # new [object] [namespace] new() { CHANGE=$(echo ${1} | tr [:lower:] [:upper:]) OBJECT=${2:-HEAD} NAMESPACE=${3:-${GIT_NOTARY_NAMESPACE}} if echo ${CHANGE} | grep -qE '^(MAJOR|MINOR|PATCH)$'; then git notes --ref=${NAMESPACE} add --message ${CHANGE} ${OBJECT} else echo MAJOR MINOR and PATCH are valid. ${CHANGE} is not. exit 23 fi } # delta (--squash) [object] [base] [namespace] delta() { if test "${1}" = '--squash'; then SQUASH=true shift fi OBJECT=${1:-HEAD} BASE=${2:-$(git describe --tags --abbrev=0)} NAMESPACE=${3:-${GIT_NOTARY_NAMESPACE}} if test "${SQUASH}" = 'true'; then NEW=$(git-notary notes ${OBJECT} ${BASE} ${NAMESPACE} | git-notary squash | git-notary versions | awk '{ print $2 }') else NEW=$(git-notary notes ${OBJECT} ${BASE} ${NAMESPACE} | git-notary versions | tail -1 | awk '{ print $2 }') fi LATEST_TAG_ON_BASE=$(git describe --tags --abbrev=0 ${BASE}) OLD=${LATEST_TAG_ON_BASE:-'0.0.0'} echo "${OLD} -> ${NEW}" } # undo [object] [namespace] undo() { OBJECT=${1:-HEAD} NAMESPACE=${2:-${GIT_NOTARY_NAMESPACE}} git notes --ref=${NAMESPACE} remove ${OBJECT} } # version version() { echo "git-notary ${GIT_NOTARY_VERSION}" } # help help() { cat < [object] [namespace] git-notary undo [object] [namespace] git-notary delta [--squash] [object] [base] [namespace] git-notary fetch [remote] [namespace] git-notary push [remote] [namespace] git-notary notes [branch] [base] [namespace] git-notary versions [initial] git-notary tags [--apply] EOF } # notary [args] notary() { COMMAND=${1} shift case ${COMMAND} in N|notes) notes ${@};; V|versions) versions ${@};; T|tags) tags ${@};; S|squash) squash ${@};; Z|squeeze) squeeze ${@};; n|new) new ${@};; u|undo) undo ${@};; d|delta) delta ${@};; P|push) push ${@};; f|fetch) fetch ${@};; fm|fetch-merge|pull) pull ${@};; M|major) new MAJOR ${@};; m|minor) new MINOR ${@};; p|patch) new PATCH ${@};; v|version|-v|--version) version;; h|help|-h|--help) help;; *) help exit 1 ;; esac } notary "${@:-}"