1# Slingshot release rules for GNU Make. 2 3# ====================================================================== 4# Copyright (C) 2001-2015 Free Software Foundation, Inc. 5# Originally by Jim Meyering, Simon Josefsson, Eric Blake, 6# Akim Demaille, Gary V. Vaughan, and others. 7# This version by Gary V. Vaughan, 2013. 8# 9# This program is free software: you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation, either version 3 of the License, or 12# (at your option) any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program. If not, see <http://www.gnu.org/licenses/>. 21# ====================================================================== 22 23NOTHING_ELSE ?= 24 25 26## --------------- ## 27## GNU Make magic. ## 28## --------------- ## 29 30# This file uses GNU Make extensions. Include it from GNUmakefile with: 31# 32# include build-aux/release.mk 33 34# Make tar archive easier to reproduce. 35export TAR_OPTIONS = --owner=0 --group=0 --numeric-owner 36 37# Helper variables. 38_empty = 39_sp = $(_empty) $(_empty) 40 41# member-check,VARIABLE,VALID-VALUES 42# ---------------------------------- 43# Check that $(VARIABLE) is in the space-separated list of VALID-VALUES, and 44# return it. Die otherwise. 45member-check = \ 46 $(strip \ 47 $(if $($(1)), \ 48 $(if $(findstring $(_sp),$($(1))), \ 49 $(error invalid $(1): '$($(1))', expected $(2)), \ 50 $(or $(findstring $(_sp)$($(1))$(_sp),$(_sp)$(2)$(_sp)), \ 51 $(error invalid $(1): '$($(1))', expected $(2)))), \ 52 $(error $(1) undefined))) 53 54include Makefile 55 56## --------- ## 57## Defaults. ## 58## --------- ## 59 60GIT ?= git 61LUA ?= lua 62LUAROCKS ?= luarocks 63TAR ?= tar 64 65# Override this in cfg.mk if you are using a different format in your 66# NEWS file. 67today ?= $(shell date +%Y-%m-%d) 68 69# Old releases are stored here. 70release_archive_dir ?= ../release 71 72# Override this in cfg.mk if you follow different procedures. 73release-prep-hook ?= release-prep 74 75_build-aux ?= build-aux 76my_distdir ?= $(PACKAGE)-$(VERSION) 77prev_version_file ?= $(srcdir)/.prev-version 78old_NEWS_hash-file ?= $(srcdir)/local.mk 79gl_noteworthy_news_ = \#\# Noteworthy changes in release ?.? (????-??-??) [?] 80 81PREV_VERSION = $(shell cat $(prev_version_file) 2>/dev/null) 82VERSION_REGEXP = $(subst .,\.,$(VERSION)) 83PREV_VERSION_REGEXP = $(subst .,\.,$(PREV_VERSION)) 84 85 86## ------------- ## 87## Distribution. ## 88## ------------- ## 89 90gitlog_to_changelog = $(srcdir)/build-aux/gitlog-to-changelog 91 92dist-hook: ChangeLog 93.PHONY: ChangeLog 94ChangeLog: 95 $(AM_V_GEN)if test -d '$(srcdir)/.git'; then \ 96 $(gitlog_to_changelog) $(gitlog_args) > '$@T'; \ 97 rm -f '$@'; mv '$@T' '$@'; \ 98 fi 99 100# Override this in GNUmakefile if you don't want to automatically 101# redistribute all the maintainer support files (take care that 102# Travis CI is finicky about this, and will likely need tweaking 103# to cope with missing any of these if you decide to omit them). 104 105_travis_yml ?= .travis.yml travis.yml.in 106 107release_extra_dist ?= \ 108 .autom4te.cfg \ 109 GNUmakefile \ 110 bootstrap \ 111 bootstrap.conf \ 112 local.mk \ 113 $(_travis_yml) \ 114 $(NOTHING_ELSE) 115 116EXTRA_DIST += \ 117 $(_build-aux)/release.mk \ 118 $(gitlog_to_changelog) \ 119 $(release_extra_dist) \ 120 $(NOTHING_ELSE) 121 122all-am: $(_travis_yml) 123 124 125## -------- ## 126## Release. ## 127## -------- ## 128 129# The vast majority of what follows is preparation -in the form 130# of early bail-out if something is not right yet- for the final 131# check-in-release-branch rule that makes the tip of the release 132# branch match the contents of a 'make distcheck' tarball. 133 134# Validate and return $(RELEASE_TYPE), or die. 135RELEASE_TYPES = alpha beta stable 136release-type = $(call member-check,RELEASE_TYPE,$(RELEASE_TYPES)) 137 138# This will actually make the release, including sending release 139# announcements, and pushing changes back to the origin. 140# Use it like this, eg: 141# make RELEASE_TYPE=beta 142.PHONY: release 143release: 144 $(AM_V_GEN)$(MAKE) $(release-type) 145 $(AM_V_GEN)$(MAKE) push 146 $(AM_V_GEN)$(MAKE) upload 147 $(AM_V_GEN)$(MAKE) mail 148 149submodule-checks ?= no-submodule-changes public-submodule-commit 150 151.PHONY: no-submodule-changes 152no-submodule-changes: 153 $(AM_V_GEN)if test -d $(srcdir)/.git \ 154 && git --version >/dev/null 2>&1; then \ 155 diff=$$(cd $(srcdir) && git submodule -q foreach \ 156 git diff-index --name-only HEAD); \ 157 case $$diff in '') ;; \ 158 *) echo '$(ME): submodule files are locally modified:'; \ 159 echo "$$diff"; exit 1;; esac; \ 160 else \ 161 : ; \ 162 fi 163 164# Ensure that each sub-module commit we're using is public. 165# Without this, it is too easy to tag and release code that 166# cannot be built from a fresh clone. 167.PHONY: public-submodule-commit 168public-submodule-commit: 169 $(AM_V_GEN)if test -d $(srcdir)/.git \ 170 && git --version >/dev/null 2>&1; then \ 171 cd $(srcdir) && \ 172 git submodule --quiet foreach \ 173 'test "$$(git rev-parse "$$sha1")" \ 174 = "$$(git merge-base origin "$$sha1")"' \ 175 || { echo '$(ME): found non-public submodule commit' >&2; \ 176 exit 1; }; \ 177 else \ 178 : ; \ 179 fi 180# This rule has a high enough utility/cost ratio that it should be a 181# dependent of "check" by default. However, some of us do occasionally 182# commit a temporary change that deliberately points to a non-public 183# submodule commit, and want to be able to use rules like "make check". 184# In that case, run e.g., "make check gl_public_submodule_commit=" 185# to disable this test. 186gl_public_submodule_commit ?= public-submodule-commit 187check: $(gl_public_submodule_commit) 188 189# These targets do all the file shuffling necessary for a release, but 190# purely locally, so you can rewind and redo before pushing anything 191# to origin or sending release announcements. Use it like this, eg: 192# 193# make beta 194.PHONY: alpha beta stable 195alpha beta stable: $(submodule-checks) 196 $(AM_V_GEN)test $@ = stable && \ 197 { echo $(VERSION) |$(EGREP) '^[0-9]+(\.[0-9]+)*$$' >/dev/null \ 198 || { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\ 199 || : 200 $(AM_V_at)$(MAKE) prev-version-check 201 $(AM_V_at)$(MAKE) vc-diff-check 202 $(AM_V_at)$(MAKE) release-commit RELEASE_TYPE=$@ 203 $(AM_V_at)$(MAKE) news-check 204 $(AM_V_at)$(MAKE) distcheck 205 $(AM_V_at)$(MAKE) check 206 $(AM_V_at)$(MAKE) $(release-prep-hook) RELEASE_TYPE=$@ 207 $(AM_V_at)$(MAKE) check-in-release-branch 208 209prev-version-check: 210 $(AM_V_at)if test -z "`$(GIT) ls-files $(prev_version_file)`"; \ 211 then \ 212 echo "error: checked in $(prev_version_file) required." >&2; \ 213 exit 1; \ 214 fi 215 216# Abort the release if there are unchecked in changes remaining. 217vc-diff-check: 218 $(AM_V_at)if ! $(GIT) diff --exit-code; then \ 219 $(GIT) diff >/dev/null; \ 220 echo "error: Some files are locally modified" >&2; \ 221 exit 1; \ 222 fi 223 224# Select which lines of NEWS are searched for $(news-check-regexp). 225# This is a sed line number spec. The default says that we search 226# only line 3 of NEWS for $(news-check-regexp), to match the behaviour 227# of '$(_build-aux)/do-release-commit-and-tag'. 228# If you want to search only lines 1-10, use "1,10". 229news-check-lines-spec ?= 3 230news-check-regexp ?= '^\#\#.* $(VERSION_REGEXP) \($(today)\)' 231 232Makefile.in: NEWS 233 234NEWS: 235 $(AM_V_GEN)if test -f NEWS.md; then ln -s NEWS.md NEWS; \ 236 elif test -f NEWS.rst; then ln -s NEWS.rst NEWS; \ 237 elif test -f NEWS.txt; then ln -s NEWS.txt NEWS; \ 238 fi 239 240news-check: NEWS 241 $(AM_V_GEN)if $(SED) -n $(news-check-lines-spec)p $< \ 242 | $(EGREP) $(news-check-regexp) >/dev/null; then \ 243 :; \ 244 else \ 245 echo 'NEWS: $$(news-check-regexp) failed to match' 1>&2; \ 246 exit 1; \ 247 fi 248 249.PHONY: release-commit 250release-commit: NEWS 251 $(AM_V_GEN)cd $(srcdir) \ 252 && $(_build-aux)/do-release-commit-and-tag \ 253 -C $(abs_builddir) $(VERSION) $(RELEASE_TYPE) 254 255define emit-commit-log 256 printf '%s\n' 'maint: post-release administrivia.' '' \ 257 '* NEWS: Add header line for next release.' \ 258 '* .prev-version: Record previous version.' \ 259 '* $(old_NEWS_hash-file) (old_NEWS_hash): Auto-update.' 260endef 261 262.PHONY: release-prep 263release-prep: $(scm_rockspec) 264 $(AM_V_GEN)$(MAKE) --no-print-directory -s announcement \ 265 > ~/announce-$(my_distdir) 266 $(AM_V_at)if test -d $(release_archive_dir); then \ 267 ln $(rel-files) $(release_archive_dir); \ 268 chmod a-w $(rel-files); \ 269 fi 270 $(AM_V_at)echo $(VERSION) > $(prev_version_file) 271 $(AM_V_at)$(MAKE) update-old-NEWS-hash 272 $(AM_V_at)perl -pi \ 273 -e '$$. == 3 and print "$(gl_noteworthy_news_)\n\n\n"' \ 274 `readlink $(srcdir)/NEWS 2>/dev/null || echo $(srcdir)/NEWS` 275 $(AM_V_at)msg=$$($(emit-commit-log)) || exit 1; \ 276 cd $(srcdir) && $(GIT) commit -s -m "$$msg" -a 277 @echo '**** Release announcement in ~/announce-$(my_distdir)' 278 279# Strip out copyright messages with years, so that changing those (e.g. 280# with 'make update-copyight') doesn't change the old_NEWS_hash. 281NEWS_hash = \ 282 $$(sed -n '/^\*.* $(PREV_VERSION_REGEXP) ([0-9-]*)/,$$p' \ 283 $(srcdir)/NEWS \ 284 | perl -0777 -pe 's/^Copyright.+?[12][0-9]{3}.+?\n//ms' \ 285 | md5sum - \ 286 | sed 's/ .*//') 287 288# Update the hash stored above. Do this after each release and 289# for any corrections to old entries. 290 291old-NEWS-regexp = '^old_NEWS_hash[ \t]+?=[ \t]+' 292update-old-NEWS-hash: NEWS 293 $(AM_V_GEN)if $(EGREP) $(old-NEWS-regexp) $(old_NEWS_hash-file); then \ 294 perl -pi -e 's/^(old_NEWS_hash[ \t]+:?=[ \t]+).*/$${1}'"$(NEWS_hash)/" \ 295 $(old_NEWS_hash-file); \ 296 else \ 297 printf '%s\n' '' "old_NEWS_hash = $(NEWS_hash)" \ 298 >> $(old_NEWS_hash-file); \ 299 fi 300 301ANNOUNCE_ENV = LUA_INIT= LUA_PATH='$(abs_srcdir)/?-git-1.rockspec' 302ANNOUNCE_PRINT = $(ANNOUNCE_ENV) $(LUA) -l$(PACKAGE) -e 303 304_PRE = " https://raw.githubusercontent" 305_POST = "/release-v$(VERSION)/$(PACKAGE)-$(VERSION)-$(rockspec_revision).rockspec" 306GITHUB_ROCKSPEC = (source.url:gsub ("^git://github", $(_PRE)):gsub ("%.git$$", $(_POST))) 307 308announcement: NEWS 309# Not $(AM_V_GEN) since the output of this command serves as 310# announcement message: else, it would start with " GEN announcement". 311 $(AM_V_at)printf '%s\n' \ 312 '# [ANN] $(PACKAGE_NAME) $(VERSION) released' \ 313 '' 314 $(AM_V_at)$(ANNOUNCE_PRINT) 'print (description.detailed)' 315 $(AM_V_at)printf '%s\n' '' \ 316 'I am happy to announce release $(VERSION) of $(PACKAGE_NAME).' \ 317 '' 318 $(AM_V_at)$(ANNOUNCE_PRINT) \ 319 'print ("$(PACKAGE_NAME)'\''s home page is at " .. description.homepage)' 320 $(AM_V_at)printf '\n' 321 $(AM_V_at)$(SED) -n \ 322 -e '/^\#\# Noteworthy changes in release $(PREV_VERSION)/q' \ 323 -e p NEWS |$(SED) -e 1,2d 324 $(AM_V_at)printf '%s\n' \ 325 'Install it with LuaRocks, using:' '' \ 326 ' luarocks install $(PACKAGE) $(VERSION)' 327 $(AM_V_at)$(ANNOUNCE_PRINT) 'print ($(GITHUB_ROCKSPEC))' 328 329 330branch = $(shell $(GIT) branch |$(SED) -ne '/^\* /{s///;p;q;}') 331GCO = $(GIT) checkout 332release-tarball = $(my_distdir).tar.gz 333 334# Anything in $(_save-files) is not removed after switching to the 335# release branch, and is thus "in the release". Add addtional partial 336# filenames to save in save_release_files, for example: 337# save_release_files = RELEASE-NOTES- 338_save-files = \ 339 $(release-tarball) \ 340 $(save_release_files) \ 341 $(NOTHING_ELSE) 342 343 344list-to-rexp = $(SED) -e 's|^|(|' -e 's/|$$/)/' 345git-clean-files = `printf -- '-e %s ' $(_save-files)` 346grep-clean-files = `printf -- '%s|' $(_save-files) |$(list-to-rexp)` 347 348# Switch to (or create) 'release' branch, remove all files, except the 349# newly generated dist tarball, then unpack the dist tarball and check 350# in all the files it creates, and tag that as the next release. 351# Github creates automatic zipballs of tagged git revisions, so we can 352# safely use this tag in the rockspecs we distribute. 353submodule-regexp ?= '^\[submodule "' 354submodule-extract-spec ?= 's|^.*"\([^"]*\)".*$$|\1|' 355 356.PHONY: check-in-release-branch 357check-in-release-branch: 358 $(AM_V_GEN)$(GCO) -b release v$(VERSION) 2>/dev/null || $(GCO) release 359 $(AM_V_at)$(GIT) pull origin release 2>/dev/null || true 360 $(AM_V_at)if $(EGREP) $(submodule-regexp) .gitmodules >/dev/null 2>&1; then \ 361 $(EGREP) $(submodule-regexp) .gitmodules \ 362 | $(SED) $(submodule-extract-spec) | xargs rm -rf; \ 363 fi 364 $(AM_V_at)$(GIT) clean -dfx $(git-clean-files) 365 $(AM_V_at)remove_re=$(grep-clean-files); \ 366 $(GIT) rm -f `$(GIT) ls-files |$(EGREP) -v "$$remove_re"` 367 $(AM_V_at)ln -s . '$(my_distdir)' 368 $(AM_V_at)$(TAR) zxf '$(release-tarball)' 369 $(AM_V_at)rm -f '$(my_distdir)' '$(release-tarball)' 370 $(AM_V_at)$(GIT) add . 371 $(AM_V_at)$(GIT) commit -s -a -m 'Release v$(VERSION).' 372 $(AM_V_at)$(GIT) tag -s -a -m 'Full source release v$(VERSION)' release-v$(VERSION) 373 $(AM_V_at)$(GCO) $(branch) 374 375.PHONY: push 376push: 377 $(AM_V_at)$(GIT) push origin master 378 $(AM_V_at)$(GIT) push origin release 379 $(AM_V_at)$(GIT) push origin v$(VERSION) 380 $(AM_V_at)$(GIT) push origin release-v$(VERSION) 381 382.PHONY: upload 383upload: rockspecs 384 $(AM_V_at)$(LUAROCKS) upload $${API_KEY+--api-key=$$API_KEY} \ 385 '$(PACKAGE)-$(VERSION)-$(rockspec_revision).rockspec' 386 387announce_emails ?= lua-l@lists.lua.org 388 389.PHONY: mail 390mail: rockspecs 391 $(AM_V_at)cat ~/announce-$(my_distdir) \ 392 | mail -s '[ANN] $(PACKAGE) $(VERSION) released' -- \ 393 $(announce_emails) 394