+# get version
+PAT_PREFIX="(^#define[[:space:]]+${PROJECT_UC}"
+PAT_SUFFIX='[[:space:]]+)[0-9]+$'
+MAJOR=$(egrep "${PAT_PREFIX}_MAJOR${PAT_SUFFIX}" $HEADER | awk '{print $3}')
+MINOR=$(egrep "${PAT_PREFIX}_MINOR${PAT_SUFFIX}" $HEADER | awk '{print $3}')
+PATCH=$(egrep "${PAT_PREFIX}_PATCH${PAT_SUFFIX}" $HEADER | awk '{print $3}')
+if [ -z "$MAJOR" -o -z "$MINOR" -o -z "$PATCH" ]; then
+ report_err "unable to get version from $HEADER"
+fi
+
+# bump version according to level
+if [ "$RTYPE" = "major" ]; then
+ MAJOR=$(expr $MAJOR + 1)
+ MINOR=0
+ PATCH=0
+elif [ "$RTYPE" = "minor" ]; then
+ MINOR=$(expr $MINOR + 1)
+ PATCH=0
+elif [ "$RTYPE" = "patch" ]; then
+ PATCH=$(expr $PATCH + 1)
+fi
+PROJ_VER="$MAJOR.$MINOR.$PATCH"
+
+# update header with new version
+sed -E "
+ s/${PAT_PREFIX}_MAJOR${PAT_SUFFIX}/\1${MAJOR}/;
+ s/${PAT_PREFIX}_MINOR${PAT_SUFFIX}/\1${MINOR}/;
+ s/${PAT_PREFIX}_PATCH${PAT_SUFFIX}/\1${PATCH}/;
+" <"$HEADER" >"${HEADER}.tmp"
+
+# apply changes
+mv "${HEADER}.tmp" "$HEADER"
+
+# commit and tag
+TAG="${PROJECT_UC}_${MAJOR}_${MINOR}_${PATCH}"
+git commit -am "Prepare for release ${PROJ_VER}." ||
+ report_err "unable to commit changes"
+git tag -a "$TAG" -m "Release ${PROJ_VER}" || report_err "unable to create tag"
+
+# create temp working space and copy repo over
+TD=$(mktemp -d /tmp/release.XXXXXXXXXX)
+if [ ! -d "$TD" ]; then
+ report_err "unable to create temp directory"
+fi
+RELEASE_DIR="$PROJECT-$PROJ_VER"
+RELEASE_TAR="$PROJECT-$PROJ_VER.tgz"
+git clone . "$TD/$RELEASE_DIR" ||
+ report_err "unable to copy to $TD/$RELEASE_DIR"
+
+# cleanup repository files
+cd "$TD"
+if [ -d "$RELEASE_DIR" -a -d "$RELEASE_DIR/.git" ]; then
+ rm -rf "$RELEASE_DIR/.git"
+fi
+if [ -d "$RELEASE_DIR" -a -f "$RELEASE_DIR/.gitignore" ]; then
+ rm -f "$RELEASE_DIR/.gitignore"
+fi