]> git.draconx.ca Git - scripts.git/blobdiff - nanoc-post-receive
Add a script to help deploy nanoc sites.
[scripts.git] / nanoc-post-receive
diff --git a/nanoc-post-receive b/nanoc-post-receive
new file mode 100755 (executable)
index 0000000..8b3a31a
--- /dev/null
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# Copyright © 2018 Nick Bowler
+#
+# Simple git post-receive hook to deploy a nanoc site
+#
+# License WTFPL2: Do What The Fuck You Want To Public License, version 2.
+# This is free software: you are free to do what the fuck you want to.
+# There is NO WARRANTY, to the extent permitted by law.
+
+GIT=/usr/bin/git
+worktreedir=/var/cache/git-worktrees
+
+master_update=
+while read old new ref x; do
+  case $ref in
+  refs/heads/master) master_update=$new ;;
+  esac
+done
+
+worktree_remove() {
+  # welp, git doesn't appear to have a way to ONLY remove worktree tracking
+  # files, it removes the work tree itself which we don't want to do.  So do
+  # this manually.
+
+  for f in worktrees/*/gitdir; do
+    exec 3<"$f" || continue
+    read l <&3 || continue
+
+    if test x"$l" = x"$1/.git"; then
+      rm -f "$f"
+      $GIT worktree prune -v
+      break
+    fi
+  done
+
+  exec 3<&-
+}
+
+cd_to_worktree_ () {
+  tmpfile=`mktemp`
+  exec 3>"$tmpfile" 4<"$tmpfile"
+  rm -f "$tmpfile"
+
+  branch=${1##*/}
+
+  repodir=`pwd`
+  reponame=${repodir##*/}
+  worktree=/no/where
+
+  # Remove any stale worktrees...
+  $GIT worktree prune -v
+
+  # First just try to add a new worktree
+  tmp_worktree=`mktemp -d "${worktreedir%/}/$reponame-$branch-XXXXXXXX"`
+  $GIT worktree add "$tmp_worktree" "$branch" 2>/dev/null ||
+    rmdir "$tmp_worktree"
+
+  $GIT worktree list --porcelain >&3
+  exec 3<&-
+
+  while read a b x <&4; do
+    case $a in
+    worktree) worktree=${b:-/no/where} ;;
+    branch) if test x"$b" = x"refs/heads/$branch"; then
+      if cd "$worktree"; then
+        test x"`pwd -P`" != x"$worktree" || { exec 4<&-; return 0; }
+        cd -
+      fi
+
+      # Clean up
+      worktree_remove "$worktree"
+    fi ;;
+    esac
+  done
+
+  # Failed?
+  exec 4<&-
+  return 1
+}
+
+# Usage: cd_to_worktree branch
+#
+# Change the current working directory to the worktree for the specified
+# branch, creating it if necessary.
+cd_to_worktree () {
+  # Try twice: stale entries might be removed by first pass and 2nd will work
+  if cd_to_worktree_ "$@" || cd_to_worktree_ "$@"; then
+    printf 'using worktree %s\n' "`pwd -P`"
+    unset GIT_DIR
+  fi
+}
+
+deploy_branch () {
+  printf 'Deploying %s\n' "$1"
+  ( cd_to_worktree $1
+    { flock -w 60 9 || exit
+      git reset --hard || exit
+      git clean -qfd -e gitlock || exit
+      nanoc || exit
+      nanoc deploy master || exit
+    } 9>gitlock
+  )
+}
+
+ret=true
+if test ${master_update:+y}; then
+  deploy_branch master || ret=false
+fi
+
+$ret