# Slingshot release rules for GNU Make.
# ======================================================================
# Copyright (C) 2001-2015 Free Software Foundation, Inc.
# Originally by Jim Meyering, Simon Josefsson, Eric Blake,
# Akim Demaille, Gary V. Vaughan, and others.
# This version by Gary V. Vaughan, 2013.
#
# 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 <http://www.gnu.org/licenses/>.
# ======================================================================
NOTHING_ELSE ?=
## --------------- ##
## GNU Make magic. ##
## --------------- ##
# This file uses GNU Make extensions. Include it from GNUmakefile with:
#
# include build-aux/release.mk
# Make tar archive easier to reproduce.
export TAR_OPTIONS = --owner=0 --group=0 --numeric-owner
# Helper variables.
_empty =
_sp = $(_empty) $(_empty)
# member-check,VARIABLE,VALID-VALUES
# ----------------------------------
# Check that $(VARIABLE) is in the space-separated list of VALID-VALUES, and
# return it. Die otherwise.
member-check = \
$(strip \
$(if $($(1)), \
$(if $(findstring $(_sp),$($(1))), \
$(error invalid $(1): '$($(1))', expected $(2)), \
$(or $(findstring $(_sp)$($(1))$(_sp),$(_sp)$(2)$(_sp)), \
$(error invalid $(1): '$($(1))', expected $(2)))), \
$(error $(1) undefined)))
include Makefile
## --------- ##
## Defaults. ##
## --------- ##
GIT ?= git
LUA ?= lua
LUAROCKS ?= luarocks
TAR ?= tar
# Override this in cfg.mk if you are using a different format in your
# NEWS file.
today ?= $(shell date +%Y-%m-%d)
# Old releases are stored here.
release_archive_dir ?= ../release
# Override this in cfg.mk if you follow different procedures.
release-prep-hook ?= release-prep
_build-aux ?= build-aux
my_distdir ?= $(PACKAGE)-$(VERSION)
prev_version_file ?= $(srcdir)/.prev-version
old_NEWS_hash-file ?= $(srcdir)/local.mk
gl_noteworthy_news_ = \#\# Noteworthy changes in release ?.? (????-??-??) [?]
PREV_VERSION = $(shell cat $(prev_version_file) 2>/dev/null)
VERSION_REGEXP = $(subst .,\.,$(VERSION))
PREV_VERSION_REGEXP = $(subst .,\.,$(PREV_VERSION))
## ------------- ##
## Distribution. ##
## ------------- ##
gitlog_to_changelog = $(srcdir)/build-aux/gitlog-to-changelog
dist-hook: ChangeLog
.PHONY: ChangeLog
ChangeLog:
$(AM_V_GEN)if test -d '$(srcdir)/.git'; then \
$(gitlog_to_changelog) $(gitlog_args) > '$@T'; \
rm -f '$@'; mv '$@T' '$@'; \
fi
# Override this in GNUmakefile if you don't want to automatically
# redistribute all the maintainer support files (take care that
# Travis CI is finicky about this, and will likely need tweaking
# to cope with missing any of these if you decide to omit them).
_travis_yml ?= .travis.yml travis.yml.in
release_extra_dist ?= \
.autom4te.cfg \
GNUmakefile \
bootstrap \
bootstrap.conf \
local.mk \
$(_travis_yml) \
$(NOTHING_ELSE)
EXTRA_DIST += \
$(_build-aux)/release.mk \
$(gitlog_to_changelog) \
$(release_extra_dist) \
$(NOTHING_ELSE)
all-am: $(_travis_yml)
## -------- ##
## Release. ##
## -------- ##
# The vast majority of what follows is preparation -in the form
# of early bail-out if something is not right yet- for the final
# check-in-release-branch rule that makes the tip of the release
# branch match the contents of a 'make distcheck' tarball.
# Validate and return $(RELEASE_TYPE), or die.
RELEASE_TYPES = alpha beta stable
release-type = $(call member-check,RELEASE_TYPE,$(RELEASE_TYPES))
# This will actually make the release, including sending release
# announcements, and pushing changes back to the origin.
# Use it like this, eg:
# make RELEASE_TYPE=beta
.PHONY: release
release:
$(AM_V_GEN)$(MAKE) $(release-type)
$(AM_V_GEN)$(MAKE) push
$(AM_V_GEN)$(MAKE) upload
$(AM_V_GEN)$(MAKE) mail
submodule-checks ?= no-submodule-changes public-submodule-commit
.PHONY: no-submodule-changes
no-submodule-changes:
$(AM_V_GEN)if test -d $(srcdir)/.git \
&& git --version >/dev/null 2>&1; then \
diff=$$(cd $(srcdir) && git submodule -q foreach \
git diff-index --name-only HEAD); \
case $$diff in '') ;; \
*) echo '$(ME): submodule files are locally modified:'; \
echo "$$diff"; exit 1;; esac; \
else \
: ; \
fi
# Ensure that each sub-module commit we're using is public.
# Without this, it is too easy to tag and release code that
# cannot be built from a fresh clone.
.PHONY: public-submodule-commit
public-submodule-commit:
$(AM_V_GEN)if test -d $(srcdir)/.git \
&& git --version >/dev/null 2>&1; then \
cd $(srcdir) && \
git submodule --quiet foreach \
'test "$$(git rev-parse "$$sha1")" \
= "$$(git merge-base origin "$$sha1")"' \
|| { echo '$(ME): found non-public submodule commit' >&2; \
exit 1; }; \
else \
: ; \
fi
# This rule has a high enough utility/cost ratio that it should be a
# dependent of "check" by default. However, some of us do occasionally
# commit a temporary change that deliberately points to a non-public
# submodule commit, and want to be able to use rules like "make check".
# In that case, run e.g., "make check gl_public_submodule_commit="
# to disable this test.
gl_public_submodule_commit ?= public-submodule-commit
check: $(gl_public_submodule_commit)
# These targets do all the file shuffling necessary for a release, but
# purely locally, so you can rewind and redo before pushing anything
# to origin or sending release announcements. Use it like this, eg:
#
# make beta
.PHONY: alpha beta stable
alpha beta stable: $(submodule-checks)
$(AM_V_GEN)test $@ = stable && \
{ echo $(VERSION) |$(EGREP) '^[0-9]+(\.[0-9]+)*$$' >/dev/null \
|| { echo "invalid version string: $(VERSION)" 1>&2; exit 1;};}\
|| :
$(AM_V_at)$(MAKE) prev-version-check
$(AM_V_at)$(MAKE) vc-diff-check
$(AM_V_at)$(MAKE) release-commit RELEASE_TYPE=$@
$(AM_V_at)$(MAKE) news-check
$(AM_V_at)$(MAKE) distcheck
$(AM_V_at)$(MAKE) check
$(AM_V_at)$(MAKE) $(release-prep-hook) RELEASE_TYPE=$@
$(AM_V_at)$(MAKE) check-in-release-branch
prev-version-check:
$(AM_V_at)if test -z "`$(GIT) ls-files $(prev_version_file)`"; \
then \
echo "error: checked in $(prev_version_file) required." >&2; \
exit 1; \
fi
# Abort the release if there are unchecked in changes remaining.
vc-diff-check:
$(AM_V_at)if ! $(GIT) diff --exit-code; then \
$(GIT) diff >/dev/null; \
echo "error: Some files are locally modified" >&2; \
exit 1; \
fi
# Select which lines of NEWS are searched for $(news-check-regexp).
# This is a sed line number spec. The default says that we search
# only line 3 of NEWS for $(news-check-regexp), to match the behaviour
# of '$(_build-aux)/do-release-commit-and-tag'.
# If you want to search only lines 1-10, use "1,10".
news-check-lines-spec ?= 3
news-check-regexp ?= '^\#\#.* $(VERSION_REGEXP) \($(today)\)'
Makefile.in: NEWS
NEWS:
$(AM_V_GEN)if test -f NEWS.md; then ln -s NEWS.md NEWS; \
elif test -f NEWS.rst; then ln -s NEWS.rst NEWS; \
elif test -f NEWS.txt; then ln -s NEWS.txt NEWS; \
fi
news-check: NEWS
$(AM_V_GEN)if $(SED) -n $(news-check-lines-spec)p $< \
| $(EGREP) $(news-check-regexp) >/dev/null; then \
:; \
else \
echo 'NEWS: $$(news-check-regexp) failed to match' 1>&2; \
exit 1; \
fi
.PHONY: release-commit
release-commit: NEWS
$(AM_V_GEN)cd $(srcdir) \
&& $(_build-aux)/do-release-commit-and-tag \
-C $(abs_builddir) $(VERSION) $(RELEASE_TYPE)
define emit-commit-log
printf '%s\n' 'maint: post-release administrivia.' '' \
'* NEWS: Add header line for next release.' \
'* .prev-version: Record previous version.' \
'* $(old_NEWS_hash-file) (old_NEWS_hash): Auto-update.'
endef
.PHONY: release-prep
release-prep: $(scm_rockspec)
$(AM_V_GEN)$(MAKE) --no-print-directory -s announcement \
> ~/announce-$(my_distdir)
$(AM_V_at)if test -d $(release_archive_dir); then \
ln $(rel-files) $(release_archive_dir); \
chmod a-w $(rel-files); \
fi
$(AM_V_at)echo $(VERSION) > $(prev_version_file)
$(AM_V_at)$(MAKE) update-old-NEWS-hash
$(AM_V_at)perl -pi \
-e '$$. == 3 and print "$(gl_noteworthy_news_)\n\n\n"' \
`readlink $(srcdir)/NEWS 2>/dev/null || echo $(srcdir)/NEWS`
$(AM_V_at)msg=$$($(emit-commit-log)) || exit 1; \
cd $(srcdir) && $(GIT) commit -s -m "$$msg" -a
@echo '**** Release announcement in ~/announce-$(my_distdir)'
# Strip out copyright messages with years, so that changing those (e.g.
# with 'make update-copyight') doesn't change the old_NEWS_hash.
NEWS_hash = \
$$(sed -n '/^\*.* $(PREV_VERSION_REGEXP) ([0-9-]*)/,$$p' \
$(srcdir)/NEWS \
| perl -0777 -pe 's/^Copyright.+?[12][0-9]{3}.+?\n//ms' \
| md5sum - \
| sed 's/ .*//')
# Update the hash stored above. Do this after each release and
# for any corrections to old entries.
old-NEWS-regexp = '^old_NEWS_hash[ \t]+?=[ \t]+'
update-old-NEWS-hash: NEWS
$(AM_V_GEN)if $(EGREP) $(old-NEWS-regexp) $(old_NEWS_hash-file); then \
perl -pi -e 's/^(old_NEWS_hash[ \t]+:?=[ \t]+).*/$${1}'"$(NEWS_hash)/" \
$(old_NEWS_hash-file); \
else \
printf '%s\n' '' "old_NEWS_hash = $(NEWS_hash)" \
>> $(old_NEWS_hash-file); \
fi
ANNOUNCE_ENV = LUA_INIT= LUA_PATH='$(abs_srcdir)/?-git-1.rockspec'
ANNOUNCE_PRINT = $(ANNOUNCE_ENV) $(LUA) -l$(PACKAGE) -e
_PRE = " https://raw.githubusercontent"
_POST = "/release-v$(VERSION)/$(PACKAGE)-$(VERSION)-$(rockspec_revision).rockspec"
GITHUB_ROCKSPEC = (source.url:gsub ("^git://github", $(_PRE)):gsub ("%.git$$", $(_POST)))
announcement: NEWS
# Not $(AM_V_GEN) since the output of this command serves as
# announcement message: else, it would start with " GEN announcement".
$(AM_V_at)printf '%s\n' \
'# [ANN] $(PACKAGE_NAME) $(VERSION) released' \
''
$(AM_V_at)$(ANNOUNCE_PRINT) 'print (description.detailed)'
$(AM_V_at)printf '%s\n' '' \
'I am happy to announce release $(VERSION) of $(PACKAGE_NAME).' \
''
$(AM_V_at)$(ANNOUNCE_PRINT) \
'print ("$(PACKAGE_NAME)'\''s home page is at " .. description.homepage)'
$(AM_V_at)printf '\n'
$(AM_V_at)$(SED) -n \
-e '/^\#\# Noteworthy changes in release $(PREV_VERSION)/q' \
-e p NEWS |$(SED) -e 1,2d
$(AM_V_at)printf '%s\n' \
'Install it with LuaRocks, using:' '' \
' luarocks install $(PACKAGE) $(VERSION)'
$(AM_V_at)$(ANNOUNCE_PRINT) 'print ($(GITHUB_ROCKSPEC))'
branch = $(shell $(GIT) branch |$(SED) -ne '/^\* /{s///;p;q;}')
GCO = $(GIT) checkout
release-tarball = $(my_distdir).tar.gz
# Anything in $(_save-files) is not removed after switching to the
# release branch, and is thus "in the release". Add addtional partial
# filenames to save in save_release_files, for example:
# save_release_files = RELEASE-NOTES-
_save-files = \
$(release-tarball) \
$(save_release_files) \
$(NOTHING_ELSE)
list-to-rexp = $(SED) -e 's|^|(|' -e 's/|$$/)/'
git-clean-files = `printf -- '-e %s ' $(_save-files)`
grep-clean-files = `printf -- '%s|' $(_save-files) |$(list-to-rexp)`
# Switch to (or create) 'release' branch, remove all files, except the
# newly generated dist tarball, then unpack the dist tarball and check
# in all the files it creates, and tag that as the next release.
# Github creates automatic zipballs of tagged git revisions, so we can
# safely use this tag in the rockspecs we distribute.
submodule-regexp ?= '^\[submodule "'
submodule-extract-spec ?= 's|^.*"\([^"]*\)".*$$|\1|'
.PHONY: check-in-release-branch
check-in-release-branch:
$(AM_V_GEN)$(GCO) -b release v$(VERSION) 2>/dev/null || $(GCO) release
$(AM_V_at)$(GIT) pull origin release 2>/dev/null || true
$(AM_V_at)if $(EGREP) $(submodule-regexp) .gitmodules >/dev/null 2>&1; then \
$(EGREP) $(submodule-regexp) .gitmodules \
| $(SED) $(submodule-extract-spec) | xargs rm -rf; \
fi
$(AM_V_at)$(GIT) clean -dfx $(git-clean-files)
$(AM_V_at)remove_re=$(grep-clean-files); \
$(GIT) rm -f `$(GIT) ls-files |$(EGREP) -v "$$remove_re"`
$(AM_V_at)ln -s . '$(my_distdir)'
$(AM_V_at)$(TAR) zxf '$(release-tarball)'
$(AM_V_at)rm -f '$(my_distdir)' '$(release-tarball)'
$(AM_V_at)$(GIT) add .
$(AM_V_at)$(GIT) commit -s -a -m 'Release v$(VERSION).'
$(AM_V_at)$(GIT) tag -s -a -m 'Full source release v$(VERSION)' release-v$(VERSION)
$(AM_V_at)$(GCO) $(branch)
.PHONY: push
push:
$(AM_V_at)$(GIT) push origin master
$(AM_V_at)$(GIT) push origin release
$(AM_V_at)$(GIT) push origin v$(VERSION)
$(AM_V_at)$(GIT) push origin release-v$(VERSION)
.PHONY: upload
upload: rockspecs
$(AM_V_at)$(LUAROCKS) upload $${API_KEY+--api-key=$$API_KEY} \
'$(PACKAGE)-$(VERSION)-$(rockspec_revision).rockspec'
announce_emails ?= lua-l@lists.lua.org
.PHONY: mail
mail: rockspecs
$(AM_V_at)cat ~/announce-$(my_distdir) \
| mail -s '[ANN] $(PACKAGE) $(VERSION) released' -- \
$(announce_emails)