]> Lady’s Gitweb - Yseme/commitdiff
Initial commit 0.1.0
authorLady <redacted>
Sun, 21 Jan 2024 00:35:28 +0000 (19:35 -0500)
committerLady <redacted>
Sun, 21 Jan 2024 01:51:07 +0000 (20:51 -0500)
GNUmakefile [new file with mode: 0644]
README.markdown [new file with mode: 0644]

diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644 (file)
index 0000000..8baaf0f
--- /dev/null
@@ -0,0 +1,77 @@
+SHELL = /bin/sh
+
+# © 2023–2024 Lady [@ Lady’s Computer].
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+# If a copy of the MPL was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+
+BUILDTARGET := .grass
+DESTDIR := .
+
+CLIENTCHARSET := utf-8-mac
+SERVER := computer
+SERVERCHARSET := utf-8
+SERVERPATH := $(notdir $(abspath .))
+
+AWK := awk
+ECHO := echo
+SED := sed
+TEST := test
+
+GIT := git
+GITFORCE :=
+GITOPTS :=
+
+# This Makefile requires rsync 3 or newer.
+RSYNC := rsync
+ifneq ($(wildcard .rsync-filter),)
+RSYNCFILTER := .rsync-filter
+endif
+RSYNCOPTS := --checksum --compress --del --links --omit-dir-times --prune-empty-dirs --recursive --times --verbose
+
+override comma := ,
+
+ifneq ($(wildcard $(BUILDTARGET)),)
+override buildtime := $(shell stat -f '%m' $(BUILDTARGET))
+endif
+
+override committime := $(shell $(GIT) $(GITOPTS) log -1 --format='%ct' | $(AWK) '{print $$NF}' || true)
+ifneq ($(committime),)
+override gitstatus := $(shell $(GIT) $(GITOPTS) status --porcelain)
+endif
+
+ensure-build:
+ifeq ($(committime),)
+       @$(ECHO) 'Error: Unable to get commit time of most recent commit!' >&2
+       @false
+endif
+ifeq ($(buildtime),)
+       @$(ECHO) 'Error: The website has not been built yet!' >&2
+       @$(ECHO) 'Run `make´ before syncing.' >&2
+       @false
+endif
+       @if $(TEST) '$(committime)' -gt '$(buildtime)'; then $(ECHO) 'Error: A commit was made after the last build!' >&2; $(ECHO) 'Run `make´ before syncing.' >&2; false; fi
+
+ensure-branch-up-to-date:
+ifeq ($(committime),)
+       @$(ECHO) 'Error: Unable to get commit time of most recent commit!' >&2
+       @false
+endif
+       $(GIT)$(if $(GITOPTS), $(GITOPTS),) fetch
+       @if ! $(GIT) $(GITOPTS) merge-base --is-ancestor @{u} HEAD; then $(ECHO) 'Error: This branch is currently out‐of‐date!' >&2; $(ECHO) 'Pull in changes with `$(GIT)$(if $(GITOPTS), $(GITOPTS),) pull´ before syncing.' >&2; false; fi
+
+ensure-clean:
+ifneq ($(gitstatus),)
+       @$(ECHO) 'Error: There are uncommitted changes!' >&2
+       @$(ECHO) 'Commit changes and run `make´ before syncing.' >&2
+       @false
+endif
+
+dry-sync: ensure-clean$(if $(GITFORCE),, ensure-branch-up-to-date) ensure-build
+       cd $(DESTDIR) && $(RSYNC) --dry-run$(if $(RSYNCFILTER), --filter='. $(abspath $(RSYNCFILTER))',)$(if $(and $(CLIENTCHARSET),$(SERVERCHARSET),$(filter-out $(CLIENTCHARSET),$(SERVERCHARSET))), --iconv='$(CLIENTCHARSET)$(comma)$(SERVERCHARSET)',) $(RSYNCOPTS) . $(SERVER):$(SERVERPATH)
+
+sync: ensure-clean$(if $(GITFORCE),, ensure-branch-up-to-date) ensure-build
+       $(GIT)$(if $(GITOPTS), $(GITOPTS),) push$(if $(GITFORCE), --force,)
+       cd $(DESTDIR) && $(RSYNC)$(if $(RSYNCFILTER), --filter='. $(abspath $(RSYNCFILTER))',)$(if $(and $(CLIENTCHARSET),$(SERVERCHARSET),$(filter-out $(CLIENTCHARSET),$(SERVERCHARSET))), --iconv='$(CLIENTCHARSET)$(comma)$(SERVERCHARSET)',) $(RSYNCOPTS) . $(SERVER):$(SERVERPATH)
+
+.PHONY: dry-sync ensure-branch-up-to-date ensure-build ensure-clean sync;
diff --git a/README.markdown b/README.markdown
new file mode 100644 (file)
index 0000000..e093ca5
--- /dev/null
@@ -0,0 +1,158 @@
+# 👥📤 Yseme
+
+**A make·file for syncing.**
+
+👥📤 Yseme is an implementation of the sync process described in my
+  blogpost [<cite>C·I pipelines have you down? Why not ‹ touch
+  .grass ›?!</cite>][touch_grass].
+It is intended to be included in projects as a Git submodule, and
+  recursively called from within another make·file.
+
+**Note:**
+👥📤 Yseme requires functionality present in G·N·U Make 3.81 (or
+  later) and will not work in previous versions, or other
+  implementations of Make.
+Compatibility with later versions of G·N·U Make is assumed, but not
+  tested.
+
+## Nomenclature
+
+<i>Yseme</i> combines two archaic English terms: <i>y‐</i> (indicating
+  togetherness or wholeness) and <i>seme</i> (< Old Norse <i>sǿmr</i>,
+  meaning “seemly”, “appropriate”, or “beautiful”).
+
+## Basic Usage
+
+`make dry-sync` will ensure that the current repository is clean,
+  built, and up‐to‐date, and then perform a dry run (`--dry-run`) of
+  R·Sync.
+`make sync` will perform the same checks, then push any new commits and
+  perform an actual run of R·Sync.
+
+👥📤 Yseme is intended to be called recursively from with·in another
+  make·file.
+The following is a sample make·file which makes use of 👥📤 Yseme :⁠—
+
+```make
+SHELL = /bin/sh
+
+# © 2024 Lady [@ Lady’s Computer].
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+# If a copy of the MPL was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+
+# Assume 👥📤 Yseme is a git submodule located at <.yseme> in the
+# current directory.
+YSEME := .yseme
+YSEMEVARS := DESTDIR='public'
+
+# Build script (substitute with your own).
+build:
+       if [ ! -d public ]; then mkdir public; fi
+       echo 'Hello, world!' > public/index
+       touch .grass
+
+# Set up the 👥📤 Yseme submodule.
+$(YSEME)/GNUmakefile:
+       git submodule update --init $(YSEME)
+
+# Reload this make·file if the 👥📤 Yseme make·file has changed.
+# (Replace `GNUmakefile´ with whatever your make·file is called.)
+#
+# This is required to ensure the correct value of the `YSEME_TARGETS´ variable.
+#
+# See <https://www.gnu.org/software/make/manual/html_node/Remaking-Makefiles.html>.
+GNUmakefile: $(YSEME)/GNUmakefile
+       touch GNUmakefile
+
+# Ensure the 👥📤 Yseme make·file exists before running the following commands.
+ifneq ($(wildcard $(YSEME)/GNUmakefile),)
+# Programmatically get the list of phony targets defined by 👥📤 Yseme.
+# You can also list these manually (e·g `sync´, `dry-sync´).
+YSEME_TARGETS := $(shell sed '/^\.PHONY[ :]/!d;/^\.PHONY[ :]/s/ *;.*//;/^\.PHONY[ :]/s/\.PHONY.*: *//' < $(YSEME)/GNUmakefile)
+
+# For each target defined by 👥📤 Yseme, forward it appropriately.
+$(YSEME_TARGETS):
+       $(MAKE) -f $(YSEME)/GNUmakefile $@ $(YSEMEVARS)
+endif
+```
+
+👥📤 Yseme was designed and tested with G·N·U Make 3.81.
+It likely works with newer versions of Make, but may break in older
+  versions.
+
+## Setup and Configuration
+
+👥📤 Yseme depends on the following programs to run.
+In every case, you may supply your own implementation by overriding the
+  corresponding (allcaps) variable (e·g, set `RSYNC` to supply your own
+  `rsync` implementation).
+
+- `awk`
+- `echo`
+- `git`
+- `rsync` (version 3.0 or later)
+- `sed`
+- `test`
+
+The following varibales provide general configuration :⁠—
+
+- **`BUILDTARGET`:**
+  A file whose timestamp is guaranteed to be updated on every build
+    (default: `.grass`).
+  👥📤 Yseme will compare the modified time of this file to the commit
+    time of the latest commit to determine if the build is out·of·date.
+
+- **`DESTDIR`:**
+  The directory which contains the result of the build.
+  `rsync` will be called from this directory.
+
+The following variables configure Git :⁠—
+
+- **`GITFORCE`:**
+  If this variable has a value, the current branch does not need to be
+    up·to·date with its remote counterpart and a force‐push will be
+    used (default: empty).
+
+- **`GITOPTS`:**
+  Options to pass to Git (default: empty).
+
+The following variables configuer R·Sync :⁠—
+
+- **`CLIENTCHARSET`:**
+  The character set of the local machine (default: `utf-8-mac`).
+  If both this and `SERVERCHARSET` are set and not equal, an appropriate
+    `--iconv` option will be added to the R·Sync call.
+
+- **`RSYNCFILTER`:**
+  The location (relative to the working directory) of an R·Sync filter
+    file (default: `.rsync-filter` if such a file exists; otherwise,
+    empty).
+
+- **`RSYNCOPTS`:**
+  Option to use when calling R·Sync.
+  The following flags are set by default :⁠—
+    `--checksum`, `--compress`, `--del`, `--links`, `--omit-dir-times`,
+    `--prune-empty-dirs`, `--recursive`, `--times`, `--verbose`.
+  Additional flags may be set depending on the values of variables and
+    which target is being built (e·g `dry-sync` 🆚 `sync`).
+
+- **`SERVER`:**
+  The remote machine to sync to (default: `computer`).
+
+- **`SERVERCHARSET`:**
+  The character set of the remote machine (default: `utf-8`).
+  If both this and `CLIENTCHARSET` are set and not equal, an appropriate
+    `--iconv` option will be added to the R·Sync call.
+
+- **`SERVERPATH`:**
+  The path on the remote machine to sync to (default: the name of the
+    current directory).
+
+If you use a method of syncing your website other than `rsync`, you can
+  still use 👥📤 Yseme:
+Just define your own `sync` and `dry-sync` targets which depend on
+ 👥📤 Yseme’s `ensure-clean`, `ensure-branch-up-to-date`, and
+ `ensure-build`.
+
+[touch_grass]: <https://blog.ladys.computer/2023-05-06/touch_grass/> "C·I pipelines have you down? Why not ‹ touch .grass ›?!"
This page took 0.025356 seconds and 4 git commands to generate.