/
niceSOFT
/
util-linux
Обзор
Документация
Войти
/
niceSOFT
/
util-linux
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tools/git-version-next
277 строк
9 KB
Thomas Weißschuh
treewide: use bash from PATH
23 апр 2026, 17:08
23 апр 2026, 17:08
cf514a2
Код
Авторство
О чём код?
#!/usr/bin/env bash set -e # Git utility to determine the next version number for util-linux releases # Based on the current stable/* branch and latest git tags SCRIPT_NAME=$(basename "$0") usage() { cat << EOF Usage: $SCRIPT_NAME [OPTIONS] Determine the next version number for util-linux releases based on git tags and current branch. Options: --rc Generate next release candidate version --release-master Generate final major release version (vX.Y) --release-update Generate maintenance release version (vX.Y.Z) --last-release TAG Override last release tag (for testing) --last-xy-release TAG Override last X.Y release tag (for testing) -h, --help Show this help message Version Schema: Major releases: vX.Y-rc1, vX.Y-rc2, [vX.Y-rc3], vX.Y Maintenance releases: vX.Y.Z-rc1, vX.Y.Z Notes: - Only stable/* branches are used for releases - Version tags are always prefixed with "v" - X.Y is frozen within a stable branch - Z increments for maintenance releases (vX.Y.1, vX.Y.2, etc.) - Release candidates are optional, created only when --rc is specified EOF } # Parse command line options RELEASE_TYPE="" RC_REQUESTED="" OVERRIDE_LAST_RELEASE="" OVERRIDE_LAST_XY_RELEASE="" while [[ $# -gt 0 ]]; do case $1 in --rc) RC_REQUESTED="yes" if [ -z "$RELEASE_TYPE" ]; then RELEASE_TYPE="rc" fi shift ;; --release-master) RELEASE_TYPE="master" shift ;; --release-update) RELEASE_TYPE="update" shift ;; --last-release) OVERRIDE_LAST_RELEASE="$2" shift 2 ;; --last-xy-release) OVERRIDE_LAST_XY_RELEASE="$2" shift 2 ;; -h|--help) usage exit 0 ;; *) echo "Error: Unknown option '$1'" >&2 echo "Use --help for usage information." >&2 exit 1 ;; esac done # Get current branch BRANCH=$(git rev-parse --abbrev-ref HEAD) # Validate we're on a stable branch and extract version prefix case "$BRANCH" in stable/*) BRANCH_VERSION=${BRANCH#stable/} ;; *) echo "Error: Not on a stable/* branch. Current branch: $BRANCH" >&2 echo "Releases are only generated from stable/* branches." >&2 exit 1 ;; esac # Get last tag matching this branch's version prefix (e.g. v2.42*) or use override if [ -n "$OVERRIDE_LAST_RELEASE" ]; then UL_RELEASE_LAST="$OVERRIDE_LAST_RELEASE" else UL_RELEASE_LAST=$(git tag --merged HEAD --sort='-creatordate' \ | grep "^${BRANCH_VERSION}" \ | head -1) fi # The last X.Y release is the branch version with Y-1 if [ -n "$OVERRIDE_LAST_XY_RELEASE" ]; then UL_RELEASE_LAST_XY="$OVERRIDE_LAST_XY_RELEASE" else local_x=$(echo "$BRANCH_VERSION" | sed 's/^v\([0-9][0-9]*\)\..*/\1/') local_y=$(echo "$BRANCH_VERSION" | sed 's/^v[0-9][0-9]*\.\([0-9][0-9]*\)$/\1/') UL_RELEASE_LAST_XY="v${local_x}.$(( local_y - 1 ))" fi # Safety check for --release-master: verify we're in a new branch without branch-specific tags if [ "$RELEASE_TYPE" = "master" ]; then # Check if there are any tags specific to this branch (not inherited from master) TAGS_MERGED_HEAD=$(git tag --merged HEAD | grep '^v[0-9]' || true) TAGS_MERGED_MASTER=$(git tag --merged master | grep '^v[0-9]' || true) # Tags specific to this branch are those merged into HEAD but not into master # (RC tags are expected and allowed) BRANCH_SPECIFIC_TAGS="" if [ -n "$TAGS_MERGED_HEAD" ]; then for tag in $TAGS_MERGED_HEAD; do if ! echo "$TAGS_MERGED_MASTER" | grep -q "^${tag}$"; then BRANCH_SPECIFIC_TAGS="$BRANCH_SPECIFIC_TAGS$tag"$'\n' fi done BRANCH_SPECIFIC_TAGS=$(echo "$BRANCH_SPECIFIC_TAGS" | grep -v '^$' | grep -v '\-rc[0-9]*$' || true) fi if [ -n "$BRANCH_SPECIFIC_TAGS" ] && [ -z "$OVERRIDE_LAST_RELEASE" ]; then TAG_COUNT=$(echo "$BRANCH_SPECIFIC_TAGS" | wc -l) echo "Error: --release-master should only be used before the first final release" >&2 echo "Current branch '$BRANCH' has $TAG_COUNT non-RC branch-specific tags:" >&2 echo "$BRANCH_SPECIFIC_TAGS" | sed 's/^/ /' >&2 echo "Use --release-update for maintenance releases in existing branches." >&2 exit 1 fi fi # Functions to extract version components get_rc_number() { echo "$1" | sed 's/.*-rc\([0-9][0-9]*\)$/\1/' } get_z_version() { echo "$1" | sed 's/^v[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/' } increment_version() { echo $(( $1 + 1 )) } # Determine next version based on current state and requested type determine_next_version() { local last_tag="$1" local type="$2" local rc_flag="$3" case "$last_tag:$type" in # Maintenance release candidates: vX.Y.Z-rcN v*.*.*-rc*:rc) local base_version=$(echo "$last_tag" | sed 's/-rc[0-9]*$//') local rc_num=$(get_rc_number "$last_tag") echo "${base_version}-rc$(increment_version $rc_num)" ;; v*.*.*-rc*:update|v*.*.*-rc*:) local base_version=$(echo "$last_tag" | sed 's/-rc[0-9]*$//') echo "$base_version" ;; v*.*.*-rc*:master) echo "Error: Cannot create major release from maintenance release candidate" >&2 exit 1 ;; # Final maintenance releases: vX.Y.Z v*.*.*:rc) local base_xy=$(echo "$last_tag" | sed 's/\.[0-9][0-9]*$//') local z_ver=$(get_z_version "$last_tag") echo "${base_xy}.$(increment_version $z_ver)-rc1" ;; v*.*.*:update|v*.*.*:) local base_xy=$(echo "$last_tag" | sed 's/\.[0-9][0-9]*$//') local z_ver=$(get_z_version "$last_tag") echo "${base_xy}.$(increment_version $z_ver)" ;; v*.*.*:master) # Create new major release: increment Y from last X.Y release if [ -z "$UL_RELEASE_LAST_XY" ]; then echo "Error: Cannot determine last X.Y release for new major version" >&2 exit 1 fi local x_ver=$(echo "$UL_RELEASE_LAST_XY" | sed 's/^v\([0-9][0-9]*\)\..*/\1/') local y_ver=$(echo "$UL_RELEASE_LAST_XY" | sed 's/^v[0-9][0-9]*\.\([0-9][0-9]*\)$/\1/') local new_version="v${x_ver}.$(increment_version $y_ver)" if [ "$rc_flag" = "yes" ]; then echo "${new_version}-rc1" else echo "$new_version" fi ;; # Major release candidates: vX.Y-rcN v*.*-rc*:rc) local base_version=$(echo "$last_tag" | sed 's/-rc[0-9]*$//') local rc_num=$(get_rc_number "$last_tag") echo "${base_version}-rc$(increment_version $rc_num)" ;; v*.*-rc*:master|v*.*-rc*:) local base_version=$(echo "$last_tag" | sed 's/-rc[0-9]*$//') echo "$base_version" ;; v*.*-rc*:update) local base_version=$(echo "$last_tag" | sed 's/-rc[0-9]*$//') echo "${base_version}.1" ;; # Final major releases: vX.Y v*.*:rc) echo "${last_tag}.1-rc1" ;; v*.*:update|v*.*:) echo "${last_tag}.1" ;; v*.*:master) # Create next major release: increment Y from current X.Y release local x_ver=$(echo "$last_tag" | sed 's/^v\([0-9][0-9]*\)\..*/\1/') local y_ver=$(echo "$last_tag" | sed 's/^v[0-9][0-9]*\.\([0-9][0-9]*\)$/\1/') local new_version="v${x_ver}.$(increment_version $y_ver)" if [ "$rc_flag" = "yes" ]; then echo "${new_version}-rc1" else echo "$new_version" fi ;; *) echo "Error: Unexpected tag format: $last_tag" >&2 exit 1 ;; esac } # Determine last final (non-RC) release if [[ "$UL_RELEASE_LAST" =~ -rc[0-9]+$ ]]; then UL_RELEASE_LAST_STABLE=$(git tag --merged HEAD --sort='-creatordate' \ | grep -E "^${BRANCH_VERSION}(\.[0-9]+)?$" \ | head -1) # Before the first final release, fall back to last X.Y if [ -z "$UL_RELEASE_LAST_STABLE" ]; then UL_RELEASE_LAST_STABLE="$UL_RELEASE_LAST_XY" fi else UL_RELEASE_LAST_STABLE="$UL_RELEASE_LAST" fi # Determine next version UL_RELEASE_NEXT=$(determine_next_version "$UL_RELEASE_LAST" "$RELEASE_TYPE" "$RC_REQUESTED") # Always provide the final release version (after code stabilization) if [[ "$UL_RELEASE_NEXT" =~ -rc[0-9]+$ ]]; then UL_RELEASE_NEXT_STABLE=$(echo "$UL_RELEASE_NEXT" | sed 's/-rc[0-9]*$//') else UL_RELEASE_NEXT_STABLE="$UL_RELEASE_NEXT" fi # Major version (vX.Y) of the next release UL_RELEASE_NEXT_XY=$(echo "$UL_RELEASE_NEXT_STABLE" | sed 's/^\(v[0-9][0-9]*\.[0-9][0-9]*\).*/\1/') # Output results echo "UL_RELEASE_LAST=$UL_RELEASE_LAST" echo "UL_RELEASE_LAST_STABLE=$UL_RELEASE_LAST_STABLE" echo "UL_RELEASE_LAST_XY=$UL_RELEASE_LAST_XY" echo "UL_RELEASE_NEXT=$UL_RELEASE_NEXT" echo "UL_RELEASE_NEXT_STABLE=$UL_RELEASE_NEXT_STABLE" echo "UL_RELEASE_NEXT_XY=$UL_RELEASE_NEXT_XY"