1 #@ Include file for the make-release.sh generic release builder.
2 #@ It also needs two hooks: update_stable_hook(), update_release_hook(),
3 #@ which need to "git add" what they have modified.
4 #@ The "grappa" mode needs a current_version() hook, which has to set $VERSION
5 #@ to the current program version, expected as MAJOR.MINOR.UPDATE[-whatever]
7 : ${PROGRAM:?"Need \$PROGRAM"}
8 : ${UPROGRAM:?"Need \$UPROGRAM"}
9 # For announcement only.
10 : ${MANUAL:?"May need \$MANUAL for announcement references"}
12 # When we upload balls only.
13 : ${UPLOAD:?"Need \$UPLOAD URL for scp(1)"}
15 # For announcement mail only.
17 : ${ACCOUNT:?"May need mailx(1) -A \$ACCOUNT"}
18 : ${MAILTO:?"May need \$MAILTO for announcement"}
19 : ${MAILBCC:?"May need \$MAILBCC for announcement"}
44 ORIG_LC_ALL=${LC_ALL} LC_ALL=C
47 DATE_MAN=`${date} -u +'%B %d, %Y'`
48 DATE_ISO=`${date} -u +%Y-%m-%d`
52 [ ${#} -gt 0 ] && printf '%s ' "${@}"
64 headref="`${git} rev-parse --verify HEAD`"
66 for i in `${git} rev-parse --branches=stable master^{commit}`; do
67 if [ ${headref} = ${i} ]; then
72 if [ -z "${brref}" ]; then
73 echo >&2 'Not on the [master] or a [stable/*] branch'
76 if [ "`${git} status --porcelain --ignored |
77 ${awk} 'BEGIN{no=0}{++no}END{print no}'`" -ne 0 ]; then
78 echo >&2 'Directory not clean, see git status --ignored'
81 #brname="`git branch | sed -e '/^* /b X' -e d -e :X -e 's/^* //'`"
82 brname=`${git} symbolic-ref --short HEAD`
86 vmaj=`{ echo ${VERSION}; } | ${sed} -e 's/^\([^.]\{1,\}\).*/\1/'`
87 vmin=`{ echo ${VERSION}; } |
88 ${sed} -e 's/^[^.]\{1,\}\.\([^.]\{1,\}\).*/\1/'`
89 [ ${vmin} = ${VERSION} ] && VERSION=${VERSION}.0 vmin=0
90 vupd=`{ echo ${VERSION}; } |
91 ${sed} -e 's/^[^.]\{1,\}\.[^.]\{1,\}\.\([^.-]\{1,\}\).*/\1/'`
92 [ ${vupd} = ${VERSION} ] && VERSION=${VERSION}.0 vupd=0
95 if yesno 'Is '${PROGRAM}' <v'${REL}'> correct?'; then :; else
96 echo >&2 'Bailing out'
102 stblbrname=stable/v${vmaj}.${vmin} need_stblbrname=
103 brref=`${git} rev-parse --verify ${stblbrname} 2>/dev/null`
104 if [ -z "${brref}" ]; then
105 if yesno 'Create new branch '"${stblbrname}"' after release tag'; then
108 elif [ ${brref} != ${headref} ] || [ ${brname} != ${stblbrname} ]; then
109 echo >&2 "For ${REL} we should be on ${stblbrname}, not ${brname}"
110 echo >&2 'Bailing out'
114 relbrname=release/v${VERSION}
115 brref=`${git} rev-parse --verify ${relbrname} 2>/dev/null`
116 if [ -z "${brref}" ]; then :; else
117 echo >&2 "The ${relbrname} already exists"
118 echo >&2 'Bailing out'
126 if yesno 'Shall '${PROGRAM}' v'${REL}' have a symbolic name?'; then
127 printf ' ..and it shall be known as: '
129 if yesno 'Is '"${RELSYM}"' correct?'; then :; else
130 echo >&2 'Bailing out'
133 stblmsg="Bump ${UPROGRAM} v${REL} (\"${RELSYM}\"), ${DATE_ISO}"
134 relmsg="Bump ${UPROGRAM} v${REL}.ar (\"${RELSYM}\"), ${DATE_ISO}"
135 RELSYM=" (\"${RELSYM}\")"
137 stblmsg="Bump ${UPROGRAM} v${REL}, ${DATE_ISO}"
138 relmsg="Bump ${UPROGRAM} v${REL}.ar, ${DATE_ISO}"
142 update_stable_branch() {
143 LC_ALL=${ORIG_LC_ALL} ${git} commit -S -n -m "${stblmsg}"
144 LC_ALL=${ORIG_LC_ALL} ${git} tag -s -f -m "${stblmsg}" v${REL}
146 if [ -n "${need_stblbrname}" ]; then
147 ${git} checkout -b ${stblbrname}
149 # Normally done in post-commit hook, but not once initially created
150 if yesno 'Shall i update stable/latest "symlink"?'; then
151 ${git} update-ref refs/heads/stable/latest ${stblbrname}
153 if yesno 'Shall i update stable/stable "symlink"?'; then
154 ${git} update-ref refs/heads/stable/stable ${stblbrname}
158 create_release_branch() {
159 if yesno 'Create release/ branch?'; then
160 ${git} checkout -b ${relbrname}
162 echo 'Updating files: calling update_release_hook'
165 LC_ALL=${ORIG_LC_ALL} ${git} commit -S -n -m "${relmsg}"
166 LC_ALL=${ORIG_LC_ALL} ${git} tag -s -f -m "${relmsg}" v${REL}.ar
168 if yesno 'Shall i update release/latest "symlink"?'; then
169 ${git} update-ref refs/heads/release/latest ${relbrname}
171 if yesno 'Shall i update release/stable "symlink"?'; then
172 ${git} update-ref refs/heads/release/stable ${relbrname}
175 relbrname=${stblbrname}
179 check_timeline_branch() {
180 if [ ${relbrname} != ${stblbrname} ] &&
181 `${git} rev-parse --verify timeline^{commit} >/dev/null 2>&1` &&
182 yesno 'Shall i update [timeline]?'; then
183 ${git} checkout timeline
185 ${git} archive --format=tar "v${REL}.ar" | ${tar} -x -f -
187 LC_ALL=${ORIG_LC_ALL} ${git} commit -S -n -m "${relmsg}"
192 [ ${relbrname} != ${stblbrname} ] && ${git} checkout ${stblbrname}
193 ${git} log --no-walk --decorate --oneline --branches --remotes
194 yesno 'Push git(1) repo?' && ${git} push
198 if [ ${relbrname} != ${stblbrname} ] && yesno 'Create tarballs?'; then
203 # Repack with standard tar(1) to avoid new-style headers
204 ${git} archive --format=tar --prefix="${PROGRAM}-${REL}/" v${REL}.ar |
205 ( cd "${TMPDIR}" && ${tar} -x -f - )
208 ${tar} -c -f "${PROGRAM}-${REL}.tar" "${PROGRAM}-${REL}"
209 < "${PROGRAM}-${REL}.tar" ${xz} -e -C sha256 > "${PROGRAM}-${REL}.tar.xz"
210 < "${PROGRAM}-${REL}.tar" ${gzip} > "${PROGRAM}-${REL}.tar.gz"
211 ${rm} "${PROGRAM}-${REL}.tar"
213 printf '' > "${PROGRAM}-${REL}.cksum"
214 ${openssl} sha1 "${PROGRAM}-${REL}.tar.xz" >> "${PROGRAM}-${REL}.cksum"
215 ${openssl} sha256 "${PROGRAM}-${REL}.tar.xz" >> "${PROGRAM}-${REL}.cksum"
216 ${openssl} sha512 "${PROGRAM}-${REL}.tar.xz" >> "${PROGRAM}-${REL}.cksum"
217 ${openssl} sha1 "${PROGRAM}-${REL}.tar.gz" >> "${PROGRAM}-${REL}.cksum"
218 ${openssl} sha256 "${PROGRAM}-${REL}.tar.gz" >> "${PROGRAM}-${REL}.cksum"
219 ${openssl} sha512 "${PROGRAM}-${REL}.tar.gz" >> "${PROGRAM}-${REL}.cksum"
221 echo >> "${PROGRAM}-${REL}.cksum"
222 ${gpg} --detach-sign --armor "${PROGRAM}-${REL}.tar.xz"
223 ${cat} "${PROGRAM}-${REL}.tar.xz.asc" >> "${PROGRAM}-${REL}.cksum"
224 ${gpg} --detach-sign --armor "${PROGRAM}-${REL}.tar.gz"
225 ${cat} "${PROGRAM}-${REL}.tar.gz.asc" >> "${PROGRAM}-${REL}.cksum"
232 announcement_prepare() {
234 if yesno 'Prepare announcement?'; then :; else
239 if `${git} cat-file -e ${relbr}:NEWS 2>/dev/null`; then
240 ${git} show ${relbr}:NEWS > "${TMPDIR}/.${PROGRAM}-${REL}.news"
242 printf '' > "${TMPDIR}/.${PROGRAM}-${REL}.news"
245 { echo "${relmsg}"; echo; } > "${TMPDIR}/${PROGRAM}-${REL}.txt"
246 if [ -f .git/make-release.txt ]; then
248 if [ -n "${bigballs}" ] && [ -f "${TMPDIR}/${PROGRAM}-${REL}.cksum" ]
250 cks=`< "${TMPDIR}/${PROGRAM}-${REL}.cksum" \
251 ${sed} -e 's/ //' -e '/^$/,$d'`
252 < "${TMPDIR}/${PROGRAM}-${REL}.cksum" ${sed} '1,/^$/d' \
253 > "${TMPDIR}/.${PROGRAM}-${REL}.sigs"
254 < .git/make-release.txt ${awk} \
255 -v INS="${cks}" -v SIGS="${TMPDIR}/.${PROGRAM}-${REL}.sigs" \
256 -v NEWS="${TMPDIR}/.${PROGRAM}-${REL}.news" '
257 /-----CHECKSUMS-----/{
260 for(i = 1; i <= atop; ++i){
261 match(a[i], /(\(.+\))/)
262 tfn = substr(a[i], RSTART + 1, RLENGTH - 2)
263 tpre = substr(a[i], 1, RSTART - 1)
264 tsuf = substr(a[i], RSTART + RLENGTH + 1)
265 if(fn == "" || fn != tfn)
266 printf "%s:\n", (fn = tfn)
267 printf " %6s %s\n", tpre, tsuf
271 /-----SIGNATURES-----/{
272 while(getline sl < SIGS)
277 while(getline sl < NEWS)
282 ' >> "${TMPDIR}/${PROGRAM}-${REL}.txt"
283 ${rm} -f "${TMPDIR}/.${PROGRAM}-${REL}.sigs"
285 < .git/make-release.txt ${awk} \
286 -v NEWS="${TMPDIR}/.${PROGRAM}-${REL}.news" '
288 while(getline sl < NEWS)
293 ' >> "${TMPDIR}/${PROGRAM}-${REL}.txt"
295 elif [ -f "${TMPDIR}/.${PROGRAM}-${REL}.news" ]; then
296 ${cat} "${TMPDIR}/.${PROGRAM}-${REL}.news" >> \
297 "${TMPDIR}/${PROGRAM}-${REL}.txt"
300 ${rm} -f "${TMPDIR}/.${PROGRAM}-${REL}.news"
302 LC_ALL=${ORIG_LC_ALL} ${EDITOR} "${TMPDIR}/${PROGRAM}-${REL}.txt"
304 # HTML convert ready for S-Web42
306 < "${TMPDIR}/${PROGRAM}-${REL}.txt" ${awk} -v manual="${MANUAL}" '
309 print "<?begin?><?mode icewatsm?><pre>"
321 while(match(s, /(\\?https?\??:\/\/[^ ]*)/)){
322 pre = substr(s, 1, RSTART - 1)
323 mat = substr(s, RSTART, RLENGTH)
324 s = substr(s, RSTART + RLENGTH)
325 if("\\" == substr(mat, 1, 1))
329 if(match(mat, /^https\?/))
330 mat = "https" substr(xt = mat, RSTART + 6)
331 if(match(mat, /sdaoden\.eu/))
332 mat = "<?lref" (xt ? "t " : " ") mat (xt ? "<>" xt : "") "?>"
334 mat = "<?href" (xt ? "t " : " ") mat (xt ? "<>" xt : "") "?>"
343 /^[[:space:]]*s-.*-mode[[:space:]]*$/{
346 /^(NOTES|ChangeLog)/{
352 /^(Appendix|git\(1\) shortlog)/{
368 # Create S-Web42 local references for the possible anchors:
369 # *XY*# / $XY# / -XY# / `XY${APO}# / `~XY${APO}# / "XY"#
370 # (where the mdocmx(7) anchor follows the number sign).
371 # Ideally the anchors have been automatically expanded by
372 # make-news-anchors.sh before.
374 /(^|\(|[[:space:]]+)("[^"]+"|\*[^\*]+\*|`[^'${APO}']+'${APO}'|[-~][-#\/:_.[:alnum:]]+|\$[_[:alnum:]]+)#[0-9]+/))
376 pre = (RSTART > 1) ? substr(s, 1, RSTART - 1) : ""
377 mat = substr(s, RSTART, RLENGTH)
378 s = substr(s, RSTART + RLENGTH)
380 # Unfortunately groups are not supported
381 if(match(mat, /^(\(|[[:space:]]+)/) != 0 && RLENGTH > 0){
382 pre = pre substr(mat, 1, RLENGTH)
383 mat = substr(mat, RSTART + RLENGTH)
386 match(mat, /#[0-9]+/)
387 targ = substr(mat, RSTART + 1, RLENGTH)
388 mat = substr(mat, 1, RSTART - 1)
389 res = res pre "<?lreft " manual "#" targ "<>" mat "?>"
397 print "</pre><?end?>"
399 ' > "${TMPDIR}/.${PROGRAM}-ann.html"
403 if [ -n "${bigballs}" ] && yesno 'Upload archives'; then :; else
409 echo "-put ${PROGRAM}-${REL}.tar.xz"
410 echo "-rm ${PROGRAM}-latest.tar.xz"
411 echo "-ln -s ${PROGRAM}-${REL}.tar.xz ${PROGRAM}-latest.tar.xz"
413 echo "-put ${PROGRAM}-${REL}.tar.xz.asc"
414 echo "-rm ${PROGRAM}-latest.tar.xz.asc"
415 echo "-ln -s ${PROGRAM}-${REL}.tar.xz.asc ${PROGRAM}-latest.tar.xz.asc"
417 echo "-put ${PROGRAM}-${REL}.tar.gz"
418 echo "-rm ${PROGRAM}-latest.tar.gz"
419 echo "-ln -s ${PROGRAM}-${REL}.tar.gz ${PROGRAM}-latest.tar.gz"
421 echo "-put ${PROGRAM}-${REL}.tar.gz.asc"
422 echo "-rm ${PROGRAM}-latest.tar.gz.asc"
423 echo "-ln -s ${PROGRAM}-${REL}.tar.gz.asc ${PROGRAM}-latest.tar.gz.asc"
425 if [ -n "${anntxt}" ]; then
426 echo "-put ${PROGRAM}-${REL}.txt"
427 echo "-rm ${PROGRAM}-latest.txt"
428 echo "-ln -s ${PROGRAM}-${REL}.txt ${PROGRAM}-latest.txt"
431 echo "-chmod 0644 ${PROGRAM}-${REL}.*"
433 ${sftp} -b - ${UPLOAD}
436 announcement_send() {
437 if [ -n "${anntxt}" ] && yesno 'Send announcement mail?'; then
438 LC_ALL=${ORIG_LC_ALL} ${MAILX} -A ${ACCOUNT} \
439 -s "[ANN]ounce of ${UPROGRAM} v${REL}${RELSYM}" \
440 -q "${TMPDIR}/${PROGRAM}-${REL}.txt" \
441 -b ${MAILBCC} ${MAILTO}
445 create_grappa_env() {
446 echo 'Updating files: calling update_release_hook'
448 echo 'E allora io quasi quasi prendo il treno'
452 if [ ${#} -ne 0 ]; then
453 if [ ${#} != 2 ] || [ "${1}" != grappa ] || [ -z "${2}" ]; then
454 echo >&2 'You have a hell of a lot to learn about Rock'"'"'n Roll'
461 echo 'Preparing a release on commit '"${headref}"
462 if [ -z "${grappa}" ]; then
463 printf ' The HEAD is %s\nName of release tag: ' "${brname}"
470 echo 'Grappa to be brought from '"${brname}"' to '"${grappa}"
472 printf 'Program version is %s, packager release addition shall be: ' \
475 VERSION="${VERSION}-${REL}"
479 if ${git} rev-parse --verify ${grappa} >/dev/null 2>/dev/null; then :; else
482 ${git} checkout ${i} ${grappa}
484 ${git} archive --format=tar ${headref} | ${tar} -x -f -
488 echo 'Updating files: calling update_stable_hook'
491 if [ -z "${grappa}" ]; then
493 create_release_branch
494 check_timeline_branch
505 # Finally remove the temporary instances than ran this
506 ${rm} -f .git/make-release.*