summaryrefslogtreecommitdiff
path: root/build-aux/do-release-commit-and-tag
blob: 3402bae45ed7dae10a21034c71fc3867f0c7339c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/bin/sh
# In a git/autoconf/automake-enabled project with a NEWS file and a version-
# controlled .prev-version file, automate the procedure by which we record
# the date, release-type and version string in the NEWS file.  That commit
# will serve to identify the release, so apply a signed tag to it as well.
VERSION=2018-03-07.03 # UTC

# Note: this is a bash script (could be zsh or dash)

# Copyright (C) 2009-2023 Free Software Foundation, Inc.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# Written by Jim Meyering

ME=$(basename "$0")
warn() { printf '%s: %s\n' "$ME" "$*" >&2; }
die() { warn "$*"; exit 1; }

help()
{
  cat <<EOF
Usage: $ME [OPTION...] VERSION RELEASE_TYPE

Run this script from top_srcdir to perform the final pre-release NEWS
update in which the date, release-type and version string are
recorded.  Commit that result with a log entry marking the release,
and apply a signed tag.  Run it from your project's top-level
directory.

Requirements:
- you use git for version-control
- a version-controlled .prev-version file
- a NEWS file, with line 3 identical to this:
$noteworthy_stub

Options:
  --branch=BRANCH     set release branch (default: $branch)
  -C, --builddir=DIR  location of (configured) Makefile (default: $builddir)
  --help              print this help, then exit
  --version           print version number, then exit

EXAMPLE:
To update NEWS and tag the beta 8.1 release of coreutils, I would run this:

  $ME 8.1 beta

Report bugs and patches to <bug-gnulib@gnu.org>.
EOF
  exit
}

version()
{
  year=$(echo "$VERSION" | sed 's/[^0-9].*//')
  cat <<EOF
$ME $VERSION
Copyright (C) $year Free Software Foundation, Inc,
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
EOF
  exit
}

## ------ ##
## Main.  ##
## ------ ##

# Constants.
noteworthy='* Noteworthy changes in release'
noteworthy_stub="$noteworthy ?.? (????-??-??) [?]"

# Variables.
branch=$(git branch | sed -ne '/^\* /{s///;p;q;}')
builddir=.

while test $# != 0
do
  # Handle --option=value by splitting apart and putting back on argv.
  case $1 in
    --*=*)
      opt=$(echo "$1" | sed -e 's/=.*//')
      val=$(echo "$1" | sed -e 's/[^=]*=//')
      shift
      set dummy "$opt" "$val" "$@"; shift
      ;;
  esac

  case $1 in
    --help|--version) ${1#--};;
    --branch) shift; branch=$1; shift ;;
    -C|--builddir) shift; builddir=$1; shift ;;
    --*) die "unrecognized option: $1";;
    *) break;;
  esac
done

test $# = 2 \
  || die "Usage: $ME [OPTION...] VERSION TYPE"

ver=$1
type=$2


## ---------------------- ##
## First, sanity checks.  ##
## ---------------------- ##

# Verify that $ver looks like a version number, and...
echo "$ver"|grep -E '^[0-9][0-9.]*[0-9]$' > /dev/null \
  || die "invalid version: $ver"
prev_ver=$(cat .prev-version) \
  || die 'failed to determine previous version number from .prev-version'

# Verify that $ver is sensible (> .prev-version).
case $(printf "%s\n%s\n" "$prev_ver" "$ver"|sort -V -u|tr '\n' ':') in
  "$prev_ver:$ver:") ;;
  *) die "invalid version: $ver (<= $prev_ver)";;
esac

case $type in
  alpha|beta|stable) ;;
  *) die "invalid release type: $type";;
esac

# No local modifications allowed.
case $(git diff-index --name-only HEAD) in
  '') ;;
  *) die 'this tree is dirty; commit your changes first';;
esac

# Ensure the current branch name is correct:
curr_br=$(git rev-parse --symbolic-full-name HEAD)
test "$curr_br" = "refs/heads/$branch" || die not on branch $branch

# Extract package name from Makefile.
Makefile=$builddir/Makefile
pkg=$(sed -n 's/^PACKAGE = \(.*\)/\1/p' "$Makefile") \
  || die "failed to determine package name from $Makefile"

# Check that line 3 of NEWS is the stub line about to be replaced.
test "$(sed -n 3p NEWS)" = "$noteworthy_stub" \
  || die "line 3 of NEWS must be exactly '$noteworthy_stub'"

## --------------- ##
## Then, changes.  ##
## --------------- ##

# Update NEWS to have today's date, plus desired version number and $type.
perl -MPOSIX -ni -e 'my $today = strftime "%F", localtime time;' \
 -e 'my ($type, $ver) = qw('"$type $ver"');' \
 -e 'my $pfx = "'"$noteworthy"'";' \
 -e 'print $.==3 ? "$pfx $ver ($today) [$type]\n" : $_' \
     NEWS || die 'failed to update NEWS'

printf "version %s\n\n* NEWS: Record release date.\n" "$ver" \
    | git commit -F -  -a || die 'git commit failed'
git tag -s -m "$pkg $ver" v$ver HEAD || die 'git tag failed'

# Local variables:
# indent-tabs-mode: nil
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "VERSION="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: " # UTC"
# End: