diff options
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 515 |
1 files changed, 75 insertions, 440 deletions
@@ -3,485 +3,120 @@ DATE = 1970-01-01 VERSION = 0.1.0 NAME = euandre.org NAME_UC = $(NAME) +PORT = 3333 LANGUAGES = en -## Installation prefix. Defaults to "/usr". -PREFIX = /usr -BINDIR = $(PREFIX)/bin -LIBDIR = $(PREFIX)/lib -INCLUDEDIR = $(PREFIX)/include -SRCDIR = $(PREFIX)/src/$(NAME) -SHAREDIR = $(PREFIX)/share -LOCALEDIR = $(SHAREDIR)/locale -MANDIR = $(SHAREDIR)/man -DOCDIR = $(SHAREDIR)/doc/$(NAME) -HTMLDIR = $(SHAREDIR)/html/$(NAME) -EXEC = ./ -## Where to store the installation. Empty by default. -DESTDIR = -LDLIBS = -PUBURL = public.asc.txt -FFMFLAGS = -y -hide_banner -loglevel warning -BASEURL = / - - - -.SUFFIXES: -.SUFFIXES: .adoc .conf .snippets .indexentry .feedentry .mapentry .sortdata .xml -.SUFFIXES: .htmlbody .htmlheader .htmlfooter .htmllisting .html .links .caslinks -.SUFFIXES: .txt .categorydata .gz .torrent .flac .ogg .ps .pdf .sentinel - -.adoc.conf: - mkwb conf src/global.conf $< > $@ - -.adoc.htmlbody: - mkwb htmlbody $< > $@ - -.htmlbody.html: - mkwb html $< > $@ - -.conf.htmlheader: - mkwb html -H $< > $@ - -.conf.htmlfooter: - mkwb html -F $< > $@ - -.adoc.snippets: - mkwb snippets $< > $@ - -.conf.indexentry: - mkwb indexentry $< > $@ - -.htmlbody.feedentry: - mkwb feedentry $< > $@ - -.conf.mapentry: - mkwb mapentry $< > $@ - -.conf.sortdata: - mkwb sortdata $< > $@ - -.conf.categorydata: - mkwb categorydata $< > $@ - -.adoc.links: - mkwb links $< > $@ - -.links.caslinks: - grep -Ev '^(link|image):' $< | xargs -I_ sh -c '\ - printf "%s\n" "_" | sha256sum | \ - printf "%s\t%s\n" "`cut -d" " -f1`" "_"' > $@ - -.flac.ogg: - ffmpeg $(FFMFLAGS) -i $< -ar 48000 -vn -c:a libvorbis -b:a 320k $@ - -.adoc.ps: - eslaides < $< > $@ - -.ps.pdf: - ps2pdf - < $< > $@ - all: include deps.mk - -listings.adoc = $(categories.adoc) $(indexes.adoc) -sources.adoc = $(articles.adoc) $(listings.adoc) $(pages.adoc) -sources.htmlbody = $(sources.adoc:.adoc=.htmlbody) -sources.html = $(sources.adoc:.adoc=.html) -sources.snippets = $(sources.adoc:.adoc=.snippets) -sources.snippets.gz = $(sources.adoc:.adoc=.snippets.gz) -sources.conf = $(sources.adoc:.adoc=.conf) -sources.links = $(sources.adoc:.adoc=.links) -sources.caslinks = $(sources.adoc:.adoc=.caslinks) -sources.mapentry = $(sources.adoc:.adoc=.mapentry) -articles.indexentry = $(articles.adoc:.adoc=.indexentry) -articles.feedentry = $(articles.adoc:.adoc=.feedentry) -articles.sortdata = $(articles.adoc:.adoc=.sortdata) -articles.categorydata = $(articles.adoc:.adoc=.categorydata) -listings.htmlheader = $(listings.adoc:.adoc=.htmlheader) -listings.htmlfooter = $(listings.adoc:.adoc=.htmlfooter) -listings.html = $(listings.adoc:.adoc=.html) -indexes.htmllisting = $(indexes.adoc:.adoc=.htmllisting) -categories.htmllisting = $(categories.adoc:.adoc=.htmllisting) -categories.txt = $(categories.adoc:.adoc=.txt) -categories.xml = $(categories.adoc:.adoc=.xml) -categories.xml.gz = $(categories.adoc:.adoc=.xml.gz) -sources.media.torrent = $(sources.media:=.torrent) -slides.ps = $(slides.adoc:.adoc=.ps) -slides.pdf = $(slides.adoc:.adoc=.pdf) - -sources = \ - $(sources.adoc) \ - $(sources.extras) \ - $(images.svg) \ - src/content/favicon.ico \ - src/content/favicon.png \ - src/content/style.css \ - src/content/$(PUBURL) \ - -dynamic-contents = \ - $(sources.html) \ - $(slides.pdf) \ - $(feeds.xml) \ - $(sources.media.torrent) \ - src/content/sitemap.xml \ - -static-contents = \ - $(sources.extras) \ - $(images.svg) \ - src/content/favicon.ico \ - src/content/favicon.png \ - src/content/style.css \ - src/content/$(PUBURL) \ - src/content/.well-known/security.txt \ - -dynamic-contents.gz = $(dynamic-contents:=.gz) - -static-contents.gz = \ - $(images.svg:=.gz) \ - src/content/favicon.ico.gz \ - src/content/style.css.gz \ - src/content/$(PUBURL).gz \ - src/content/.well-known/security.txt.gz \ - -contents.gz = \ - $(dynamic-contents.gz) \ - $(static-contents.gz) \ - -contents = \ - $(dynamic-contents) \ - $(static-contents) \ - -all-filelists = \ - $(sources.snippets) \ - $(sources.snippets.gz) \ - $(categories.xml) \ - $(categories.xml.gz) \ - -all-contents = \ - $(contents) \ - $(contents.gz) \ - -captured-assets = \ - src/content/$(PUBURL) \ - src/content/favicon.ico \ - src/content/favicon.png \ - -captured-assets.sentinel = $(captured-assets:=.sentinel) - - -derived-assets = \ - $(dynamic-contents) \ - $(contents.gz) \ - $(sources.html) \ - $(sources.htmlbody) \ - $(sources.snippets) \ - $(sources.snippets.gz) \ - $(sources.conf) \ - $(sources.links) \ - $(sources.caslinks) \ - $(sources.mapentry) \ - src/dyn.conf \ - src/base.conf \ - src/global.conf \ - $(articles.indexentry) \ - $(articles.feedentry) \ - $(articles.sortdata) \ - $(articles.categorydata) \ - $(listings.htmlheader) \ - $(listings.htmlfooter) \ - $(listings.html) \ - $(indexes.htmllisting) \ - $(categories.htmllisting) \ - $(categories.txt) \ - $(categories.xml) \ - $(categories.xml.gz) \ - $(slides.ps) \ - $(slides.pdf) \ - email.txt \ - baseurl.txt \ - fingerprint.txt \ - expiry.txt \ - expiry-epoch.txt \ - now.txt \ - src/content/.well-known/security.txt \ - src/all-contents.txt \ - src/all-filelists.txt \ - src/all-symlinks.txt \ - src/install.txt \ - src/sort-expected.txt \ - src/sort-given.txt \ - src/sources.txt \ - install.txt \ - sources.txt \ - src/content/.gitignore \ - $(captured-assets.sentinel) \ - -side-assets = \ - src/collections/*/*/*/*/*/*.html.*.txt \ - src/collections/*/*/*/*/*/*.txt.gz \ - src/collections/*/*/index.html.*.txt \ - src/collections/*/*/sortdata.txt \ - src/collections/*/*/feed.*.xml \ - src/collections/*/*/feed.*.xml.gz \ - src/collections/*/*/*.sortdata \ - src/pages/*/*.html.*.txt \ - src/content/.well-known/ \ - `cat src/all-symlinks.txt 2>/dev/null` \ - `cat src/linkonly-dirs.txt 2>/dev/null` \ - - - -## Default target. Builds all artifacts required for testing -## and installation. -all: $(derived-assets) -all: $(captured-assets) - - $(derived-assets): Makefile deps.mk -$(sources.conf): src/global.conf - - -src/content/.gitignore: src/symlinks.txt - cd src/content/ && mkwb symlinks ../symlinks.txt > $(@F) - -src/dyn.conf: email.txt baseurl.txt fingerprint.txt - printf "export url_pre='%s'\n" "`cat baseurl.txt`" > $@ - printf "export email='%s'\n" "`cat email.txt`" >> $@ - printf "export publickey='%s'\n" "`cat fingerprint.txt`" >> $@ - printf "export publickey_url='$(PUBURL)'\n" >> $@ - printf 'export sourcecode_url="$$url_pre/git/$(NAME)"\n' >> $@ - -src/base.conf: src/dyn.conf src/static.conf - cat src/dyn.conf src/static.conf > $@ - -src/global.conf: src/base.conf - mkwb conf -G src/base.conf > $@ - -$(listings.html): - cat $*.htmlheader $*.htmlbody $*.htmllisting $*.htmlfooter > $@ - -$(indexes.htmllisting): - mkwb indexbody $*.conf > $@ - -$(categories.htmllisting): - mkwb categoriesbody $*.conf > $@ - -$(categories.txt): src/global.conf - mkwb categories src/global.conf $(@D) > $@ - -$(categories.xml): - for f in `cat $*.txt`; do \ - c="`printf '%s\n' "$$f" | cut -d. -f2`"; \ - mkwb feed src/global.conf "$$f" > $(@D)/feed."$$c".xml; \ - printf '%s\n' $(@D)/feed."$$c".xml; \ - done > $@ - -$(feeds.xml): - mkwb feed src/global.conf $(@D)/sortdata.txt > $@ - -$(contents.gz): - gzip -9fk $* - touch $@ - -$(sources.snippets.gz) $(categories.xml.gz): - if [ -s $* ]; then gzip -9fk `cat $*`; fi - sed 's/$$/.gz/' $* > $@ - -src/content/$(PUBURL).gz: src/content/$(PUBURL).sentinel -src/content/$(PUBURL).sentinel: email.txt - gpg --export --armour "`cat email.txt`" | ifne ifnew $* - touch $@ - -src/content/favicon.ico.gz: src/content/favicon.ico.sentinel -src/content/favicon.ico.sentinel: src/content/img/favicon.svg - convert src/content/img/favicon.svg -strip ico:- | ifnew $* - touch $@ -src/content/favicon.png.sentinel: src/content/img/favicon.svg - convert src/content/img/favicon.svg -strip png:- | ifnew $* - touch $@ +## ---- what this site has beyond the canonical rules ------------- -$(sources.media.torrent): - F="`printf '%s\n' $* | cut -d/ -f3-`" && \ - mktorrent -xfd -n $(*F) -o $@ -w "https://$(NAME)$(BASEURL)$${F}" $* - -src/content/sitemap.xml.gz: src/content/sitemap.xml -src/content/sitemap.xml: $(sources.mapentry) - mkwb sitemap $(sources.mapentry) > $@ - -email.txt: meta.capim - cat meta.capim | awk '$$1 == ":email" && $$0=$$2' | tr -d '"' > $@ - -baseurl.txt: meta.capim - cat meta.capim | awk '$$1 == ":baseurl" && $$0=$$2' | tr -d '"' > $@ - -fingerprint.txt: src/content/$(PUBURL) - gpg --always-trust --no-keyring --show-key --with-colons \ - src/content/$(PUBURL) | \ - awk -F: '/^pub:/ { print $$5 }' > $@ - -expiry.txt: src/content/$(PUBURL) - gpg --always-trust --no-keyring --show-key --with-colons \ - src/content/$(PUBURL) | \ - awk -F: '/^pub:/ { print $$7 }' | \ - xargs -I% date -Is -d@% > $@ - -expiry-epoch.txt: expiry.txt - date -d "`cat expiry.txt`" '+%s' > $@ - -now.txt: - now > $@ - -src/content/.well-known/security.txt.gz: src/content/.well-known/security.txt -src/content/.well-known/security.txt: email.txt baseurl.txt expiry.txt - mkdir -p $(@D) - printf 'Contact: mailto:%s\n' "`cat email.txt`" > $@ - printf 'Expires: %s\n' "`cat expiry.txt`" >> $@ - printf 'Encryption: %s/$(PUBURL)\n' "`cat baseurl.txt`" >> $@ - printf 'Preferred-Languages: en, pt, fr, eo, es, de\n' >> $@ - -src/sources.txt: - printf '%s\n' $(sources) > $@ - -src/all-contents.txt: - printf '%s\n' $(all-contents) > $@ - -src/all-filelists.txt: src/all-symlinks.txt - printf '%s\n' $(all-filelists) src/all-symlinks.txt > $@ - -src/all-symlinks.txt: src/content/.gitignore - sed 's|^|src/content|' src/content/.gitignore > $@ - -src/install.txt: src/all-contents.txt src/all-filelists.txt $(all-filelists) - cat src/all-contents.txt `cat src/all-filelists.txt` > $@ - -sources.txt: src/sources.txt -install.txt: src/install.txt -sources.txt install.txt: - sed 's|^src/content/||' src/$(@F) > $@ - - - -src/sort-expected.txt: - dirname $(articles.adoc) | env LANG=POSIX.UTF-8 sort | uniq -c | \ - awk '{ printf "%s\t%s\n", $$2, $$1 }' > $@ - -src/sort-given.txt: $(sources.conf) src/sort-expected.txt - awk '{ \ - "grep \"^export sort=\" " $$1 "/*.conf | wc -l" | getline cnt; \ - printf "%s\t%s\n", $$1, cnt; \ - }' src/sort-expected.txt > $@ - -check-unit-sorting: src/sort-expected.txt src/sort-given.txt - diff -U10 src/sort-expected.txt src/sort-given.txt - - -.SUFFIXES: .updatedat-check -sources.updatedat-check = $(sources.adoc:.adoc=.updatedat-check) -$(sources.updatedat-check): - . ./$*.conf && if [ -n "$$updatedat_epoch" ] && \ - [ "$$updatedat_epoch" -le "$$date_epoch" ]; then exit 3; fi - -check-unit-updatedat: $(sources.updatedat-check) - - -.SUFFIXES: .links-internal-check -sources.links-internal-check = $(sources.adoc:.adoc=.links-internal-check) -$(sources.links-internal-check): $(sources.html) $(slides.pdf) - grep -E '^(link|image):' $*.links | cut -d: -f2- | \ - xargs -I% test -e $(*D)/% - -check-unit-links-internal: $(sources.links-internal-check) - - -check-unit-links-external: - - -symlink-deps = \ - $(sources.html) \ - $(feeds.xml) \ - $(categories.xml) \ - src/content/.well-known/security.txt \ - $(sources.media.torrent) \ - -check-unit-links-symlinks: src/all-symlinks.txt $(symlink-deps) - find `cat src/all-symlinks.txt` | xargs -n1 test -e - - -check-unit-links: check-unit-links-internal check-unit-links-external -check-unit-links: check-unit-links-symlinks +## The favicons this site renders from img/favicon.svg, rather than +## carrying as sources the way papo.im does: derived, so clean takes +## them. +side-assets += src/content/favicon.ico src/content/favicon.png +side-assets += have.txt want.txt stale.txt kept.txt dirs.txt rmlist.txt +integration-tests = \ -MAXSIZE = 52428800 # from spec: https://www.sitemaps.org/protocol.html -check-unit-sitemap-size: src/content/sitemap.xml - test "`stat --printf='%s' src/content/sitemap.xml`" -le $(MAXSIZE) +.PRECIOUS: $(integration-tests) +$(integration-tests): ALWAYS + sh $@ -check-unit-sitemap-count: src/content/sitemap.xml - test "`grep -cF '</url>' src/content/sitemap.xml`" -le 50000 +check-integration: $(integration-tests) -check-unit-sitemap: check-unit-sitemap-count check-unit-sitemap-size +check: check-unit check-integration -check-unit-expiry: expiry-epoch.txt now.txt - test "`cat expiry-epoch.txt`" -gt "`cat now.txt`" +i18n: + po4a po/po4a.cfg -check-unit: check-unit-sorting check-unit-updatedat check-unit-links -check-unit: check-unit-sitemap check-unit-expiry -integration-tests = \ +run: + serve -n -p $(PORT) -d '$(DESTDIR)$(HTMLDIR)' -.PRECIOUS: $(integration-tests) -$(integration-tests): ALWAYS - sh $@ +want.txt: install.txt + sort install.txt | sed 's|^|/srv/www/|' > $@ -check-integration: $(integration-tests) +## Files and links only: install.txt names no directories, so an +## unfiltered find would call every one of them stale --- /srv/www +## among them. +have.txt: + ssh euandre.org 'find /srv/www \( -type f -o -type l \)' | sort > $@ +stale.txt: have.txt want.txt + comm -23 have.txt want.txt > $@ -## Run all tests. Each test suite is isolated, so that a parallel -## build can run tests at the same time. The required artifacts -## are created if missing. -check: check-unit check-integration +## Which directories the pruning empties: those that held something +## stale and hold nothing that stays. Both are read off the two +## lists already in hand, so nothing has to walk the tree over there +## asking rmdir to refuse most of what it is offered. +## +## In no particular order: rm -rf takes a directory with whatever is +## under it, so a parent reached before its child carries the child +## away and the child's own turn finds nothing left to do. The +## sorting that remains is comm's, which needs both sides ordered. +kept.txt: have.txt want.txt stale.txt + comm -12 have.txt want.txt | ancestors /srv/www | sort -u > $@ +dirs.txt: stale.txt kept.txt + ancestors /srv/www < stale.txt | sort -u | comm -23 - kept.txt > $@ +rmlist.txt: stale.txt dirs.txt + cat stale.txt dirs.txt > $@ -i18n: - po4a po/po4a.cfg +## Prune, then send. Ask the server what it has, take away the list +## "all" already wrote, and delete what is left over; then extract. +## +## Only the stale names go, so a page that stays is never taken from +## under a reader, and there is no moment when the site is missing. +## The comparison is comm here rather than a script over there, and +## every step lands in a file that says what it holds, so what is +## about to be removed can be read before it is. +## +## Emptied by name rather than replaced wholesale: /srv is root's, so +## /srv/www's own directory entry cannot be removed or remade. +upload: rmlist.txt install.tar + cat rmlist.txt | ssh euandre.org xargs rm -rf + cat install.tar | ssh euandre.org tar -xf - -C /srv/www -## Remove *all* derived artifacts produced during the build. -## A dedicated test asserts that this is always true. +## Remove all derived artifacts produced during the build. clean: rm -rf $(derived-assets) $(side-assets) + ## The legacy-URL symlinks sit in directories mkwb symlinks had + ## to create; removing the links leaves those empty. Naming + ## them drifts the moment a link is added --- which it did --- + ## so let rmdir decide: git cannot track an empty directory, so + ## under the content root an empty one is always residue. + ## -depth walks bottom-up, which is what prunes a whole branch. + find src/content -depth -type d -exec rmdir {} + 2>/dev/null || true -## Installs into $(DESTDIR)$(PREFIX). Its dependency target -## ensures that all installable artifacts are crafted beforehand. +## Install into $(DESTDIR)$(PREFIX) by extracting what "all" +## already packed: the same two tarballs that go to a server, so +## installing next door and deploying across a network are the one +## operation. tar(1) rather than rsync(1), one fewer dependency +## outside the fleet. Unlike rsync --delete it adds without +## pruning --- an install over a tree still holding a page whose +## source is gone leaves that page there --- so install into an +## empty $(DESTDIR), or uninstall first. install: all - rsync --delete --mkpath -a --files-from=install.txt src/content/ \ - '$(DESTDIR)$(HTMLDIR)' - rsync --delete --mkpath -a --files-from=sources.txt src/content/ \ - '$(DESTDIR)$(SRCDIR)' + mkdir -p '$(DESTDIR)$(HTMLDIR)' '$(DESTDIR)$(SRCDIR)' + cat install.tar | tar -xf - -C '$(DESTDIR)$(HTMLDIR)' + cat sources.tar | tar -xf - -C '$(DESTDIR)$(SRCDIR)' -## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror -## of the "install" target, and removes *all* that was installed. -## A dedicated test asserts that this is always true. +## Remove what install placed. uninstall: rm -rf \ '$(DESTDIR)$(SRCDIR)' \ '$(DESTDIR)$(HTMLDIR)' \ - -PORT = 3333 -## Run file server for local installed static files. -run: - serve -n -p $(PORT) -d '$(DESTDIR)$(HTMLDIR)' - - ALWAYS: |
